2010-09-20 15 views
7

Ho una matrice piena di oggetti della stessa classe. Vorrei ordinare questo array dal campo oggetto opzionale, per esempio $case->ID o $case->SenderPHP Funzione di ordinamento per ordinare una matrice di oggetti

C'è una costruito nel sapore del array_sort function() che fa questo già, o dovrò scrivere questo tipo me funziona?

risposta non ha bisogno di spiegare in dettaglio - questo è più simile a una domanda sì/no

Grazie


mio tentativo fallito di 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; 
    }); 
    } 

Un altro tentativo fallito:

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; 
    } 

Modifica per urto

+0

Perché non riesce? Che risultato vedi? – codaddict

+0

Nel primo tentativo, $ sort ovviamente non è stato trovato. Nel secondo tentativo, non so come fare riferimento alla funzione 'srt'. – Hubro

risposta

10

È possibile utilizzare non solo una funzione anonima ma una chiusura, come ad es.

e $ sort saranno disponibili nel corpo della funzione. autonomo esempio:

<?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"; 
    } 
} 

stampe

----- 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 

aggiornamento: con PHP < 5.3 è possibile utilizzare un oggetto invece di una funzione anonima. usort() si aspetta che il secondo parametro sia callable. Questa può essere una funzione anormale a partire da php 5.3, ma può anche essere il nome di una funzione .... o un oggetto e un nome di metodo passati come una matrice come 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') 
); 
} 

(Se si fa largo uso di questo - o non vogliono scrivere scuse come questo -_- - si potrebbe desiderare di definire un'interfaccia come interface Comparator { ... }, lasciate Foo implementare tale interfaccia ed avere qualche funzione/classe che usa Comparator, cioè un wrapper per gli oggetti intorno a usort().)

+2

Un buon esempio di utilizzo delle chiusure. Funziona solo con PHP 5.3 o successivo – Iacopo

+0

Funziona perfettamente. Grazie! Se c'è una versione dello stesso risultato che richiede meno codice mi piacerebbe vedere anche questo: P – Hubro

+0

Scusa si scopre PHP 5.3 non sarà disponibile - Ho bisogno di un'altra soluzione – Hubro

7

È possibile utilizzare usort come:

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

usort($arrayOfObjects,'cmp'); 

in PHP> = 5.3 è anche possibile utilizzare la funzione anonima come:

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

Grazie per la risposta. Conoscete qualche metodo per ottenere una variabile predefinita in questa funzione di ordinamento? Il mio tentativo non è riuscito (l'ho modificato nel post principale) – Hubro

0

Avrete per scriverlo, ma è piuttosto banale con usort():

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

usort($cases, 'my_obj_sort'); 
0

Si dovrebbe dare un'occhiata alla funzione usort(). Accetta una richiamata che esegue l'ordinamento personalizzato, che è ciò che desideri.

0

Dal punto di vista della progettazione, un'opzione migliore sarebbe utilizzare un oggetto dedicato (come CasesCollection) anziché semplici array. È possibile rendere la chiave di ordinamento un membro di questo oggetto e banalmente fare riferimento ad essa come $this->sortKey nel callback di ordinamento.

Problemi correlati