2010-09-20 12 views
7

Tengo una matriz llena de objetos de la misma clase. Me gustaría resolver esto matriz por campo de objeto opcional, por ejemplo $case->ID o $case->SenderPHP Función de clasificación para ordenar una matriz de objetos

¿Hay un sistema incorporado en el sabor de la array_sort función() que hace esto ya, o voy a tener que escribir este tipo funcione a mí mismo?

respuesta no tiene que explicar en detalle - esto es más como una pregunta sí/no

Gracias


mi intento fallido de usort:

function sortBy($sort) 
    { 
    usort($this->abuseCases, function($a, $b) { 
    if($a->{$sort} > $b->{$sort}) return 1; 
    if($a->{$sort} < $b->{$sort}) return -1; 
    else return 0; 
    }); 
    } 

Otro intento fallido:

function sortBy($sort) 
    { 
     $this->sortBy = $sort; 

     usort($this->abuseCases, array("this", "srt")); 
    } 

    private function srt($a, $b) 
    { 
     if($a->{$this->sortBy} > $b->{$this->sortBy}) return 1; 
     if($a->{$this->sortBy} < $b->{$this->sortBy}) return -1; 
     else return 0; 
    } 

Editar para bache

+0

¿Por qué falla? ¿Qué resultado estás viendo? – codaddict

+0

En el primer intento, obviamente no se encontró $ sort. En el segundo intento, no sé cómo referirme a la función 'srt'. – Hubro

Respuesta

10

Puede utilizar no solo una función anónima sino un cierre, como p. Ej.

function ($a,$b) use ($sort) { ... } 

y $ sort estará disponible en el cuerpo de la función. autónomo ejemplo:

<?php 
function getFn($sort) { 
    return function($a, $b) use($sort) { 
    if($a->$sort > $b->$sort) return 1; 
    if($a->$sort < $b->$sort) return -1; 
    return 0; 
    }; 
} 

$abuseCases = array(
    (object)array('ID'=>1, 'Sender'=>'Sender A'), 
    (object)array('ID'=>3, 'Sender'=>'Sender D'), 
    (object)array('ID'=>2, 'Sender'=>'Sender C'), 
    (object)array('ID'=>4, 'Sender'=>'Sender B') 
); 

echo "\n----- Sort By Sender ----\n"; 
usort($abuseCases, getFn('Sender')); 
foo($abuseCases); 

echo "\n----- Sort By ID ----\n"; 
usort($abuseCases, getFn('ID')); 
foo($abuseCases); 

function foo($a) { 
    foreach($a as $o) { 
    echo $o->ID, ' ', $o->Sender, "\n"; 
    } 
} 

impresiones

----- Sort By Sender ---- 
1 Sender A 
4 Sender B 
2 Sender C 
3 Sender D 

----- Sort By ID ---- 
1 Sender A 
2 Sender C 
3 Sender D 
4 Sender B 

actualización: < con PHP 5.3 que puede utilizar un objeto en lugar de una función anónima. usort() espera que el segundo parámetro sea callable. Esa puede ser una función anónima a partir de php 5.3, pero también puede ser el nombre de una función ... o un objeto y un nombre de método pasados ​​como una matriz como array($obj, 'methodName').

$abuseCases = getData(); 
echo "\n----- Sort By Sender ----\n"; 
usort($abuseCases, array(new Foo('Sender'), 'compare')); 
foo($abuseCases); 

echo "\n----- Sort By ID ----\n"; 
usort($abuseCases, array(new Foo('ID'), 'compare')); 
foo($abuseCases); 

class Foo { 
    public $propName; // protected? 
    public function __construct($propertyName) { 
    $this->propName = $propertyName; 
    } 
    public function compare($a, $b) { 
    $prop = $this->propName; 
    if($a->$prop > $b->$prop) return 1; 
    if($a->$prop < $b->$prop) return -1; 
    return 0; 
    } 
} 

function foo($a) { 
    foreach($a as $o) { 
    echo $o->ID, ' ', $o->Sender, "\n"; 
    } 
} 
function getData() { 
    return array(
    (object)array('ID'=>1, 'Sender'=>'Sender A'), 
    (object)array('ID'=>3, 'Sender'=>'Sender D'), 
    (object)array('ID'=>2, 'Sender'=>'Sender C'), 
    (object)array('ID'=>4, 'Sender'=>'Sender B') 
); 
} 

(Si hace un uso intensivo de esto - o no quiere escribir excusas como ésta -_- - es posible que desee para definir una interfaz como interface Comparator { ... }, dejar que Foo implementar esa interfaz y tienen alguna función/clase que usa Comparator, es decir, un contenedor para objetos alrededor de usort().)

+2

Un buen ejemplo de uso de cierres. Funciona solo con PHP 5.3+ – Iacopo

+0

Funciona a la perfección. ¡Gracias! Si hay una versión del mismo resultado que requiere menos código, me encantaría ver eso también: P – Hubro

+0

Lo sentimos, PHP 5.3 no estará disponible - Necesito otra solución – Hubro

7

Usted puede utilizar usort como:

function cmp($a, $b) {  
    return ($a->ID - $b->ID); // assuming numeric ID 
} 

usort($arrayOfObjects,'cmp'); 

en PHP> = 5.3 también puede utilizar la función anónima como:

usort($arrayOfObjects, function($a, $b) { 
     return $a->ID - $b->ID; 
    }); 
+0

Gracias por la respuesta. ¿Conoces algún método para obtener una variable predefinida en esta función de clasificación? Mi intento falló (lo he editado en la publicación principal) – Hubro

0

Tendrá escribirlo, pero es bastante trivial con usort():

function my_obj_sort($a, $b) { 
    return strnatcasecmp($a->Sender, $b->Sender); 
} 

usort($cases, 'my_obj_sort'); 
0

Debería echar un vistazo a la función usort(). Acepta una devolución de llamada que realiza una clasificación personalizada, que es lo que desea.

0

Desde el punto de vista de diseño una mejor opción sería usar un objeto dedicado (como CasesCollection) en lugar de matrices simples. Puede hacer que la clave de clasificación sea un miembro de este objeto y trivialmente referirse a él como $this->sortKey en la devolución de llamada de clasificación.

Cuestiones relacionadas