2011-12-22 19 views
13

Ho la seguente matrice:Ordina serie da due proprietà degli oggetti utilizzando funzione anonima

Array 
(
    [0] => stdClass Object 
     (
      [timestamp] => 1 
      [id] => 10 
     ) 

    [1] => stdClass Object 
     (
      [timestamp] => 123 
      [id] => 1 
     ) 

    [2] => stdClass Object 
     (
      [timestamp] => 123 
      [id] => 2 
     ) 

) 

Attualmente sto usando il seguente codice per ordinare l'array dalla proprietà timestamp:

function sort_comments_by_timestamp(&$comments, $prop) 
{ 
    usort($comments, function($a, $b) use ($prop) { 
     return $a->$prop < $b->$prop ? 1 : -1; 
    }); 
} 

Come posso anche ordinare l'ID per id discendente quando il timestamp è lo stesso?

+1

C'è un motivo per cui lo chiamate '_by_timestamp', ma ha anche un parametro' $ prop'? – Matthew

+1

@Matthew diverso da "Stavo facendo alcuni test' e cattivi nomi? No :) Già risolto btw – PeeHaa

risposta

17

suggerimento è quello di inviare in un array con $ puntelli

function sort_comments_by_timestamp(&$comments, $props) 
{ 
    usort($comments, function($a, $b) use ($props) { 
     if($a->$props[0] == $b->$props[0]) 
      return $a->$props[1] < $b->$props[1] ? 1 : -1; 
     return $a->$props[0] < $b->$props[0] ? 1 : -1; 
    }); 
} 

E poi chiamare con

sort_comments_by_timestamp($unsorted_array,array("timestamp","id")); 

Se si desidera lavorare con un numero X di $ puntelli si può fare un ciclo all'interno del usort confrontando sempre una proprietà con la proprietà precedente nell'array simili:

function sort_comments_by_timestamp(&$comments, $props) 
{ 
    usort($comments, function($a, $b) use ($props) { 
     for($i = 1; $i < count($props); $i++) { 
      if($a->$props[$i-1] == $b->$props[$i-1]) 
       return $a->$props[$i] < $b->$props[$i] ? 1 : -1; 
     } 
     return $a->$props[0] < $b->$props[0] ? 1 : -1; 
    }); 
} 

Cheers!

+1

Se si ottiene errore: 'Dalla matrice alla conversione di stringhe 'è necessario sostituire tutti' $ a -> $ props [X] 'a' $ a -> {$ props [X]} ' –

2
$result = -1; 
if ($a->timestamp < $b->timestamp) { 
    $result = 1; 
} else if ($a->timestamp === $b->timestamp) { 
    if ($a->id < $b->id) $result = 1; 
} 
return $result; 

Inserirlo nella chiusura di servizio. Puoi anche eliminare l'argomento $ prop e la parte use ($prop).

3
function sort_comments_by_timestamp(&$comments, $prop) 
{ 
    usort($comments, function($a, $b) use ($prop) { 
     if ($a->$prop == $b->$prop) 
      return $b->id - $a->id; 
     else 
      return $a->$prop < $b->$prop ? 1 : -1; 
    }); 
} 

I tipi suddetti primi dal parametro $prop e poi secondarie da id.

0

ordinamento per numero arbitrario di criteri. Ho sempre dimenticato se $ a - $ b ordina in ordine ascendente o discendente. Regolare secondo necessità.

$comparatorSequence = array(
    function($a, $b) { 
     return $a->timestamp - $b->timestamp; 
    } 
    , function($a, $b) { 
     return $a->id - $b->id; 
    } 
); 

usort($theArray, function($a, $b) use ($comparatorSequence) { 
    foreach ($comparatorSequence as $cmpFn) { 
     $diff = call_user_func($cmpFn, $a, $b); 
     if ($diff !== 0) { 
      return $diff; 
     } 
    } 
    return 0; 
}); 
4

È possibile farlo con ouzo goodies (lo so che hai sentito su di esso: P).

$result = Arrays::sort($array, 
    Comparator::compound(
     Comparator::compareBy('timestamp'), 
     Comparator::compareBy('id') 
    ) 
); 
2

So che questo è abbastanza vecchia questione, tuttavia, non ha trovato tante informazioni per quando si desidera ordinare più proprietà un po 'come mySQL orderBy fa quindi ecco una funzione da un quadro personale

Opzione 1: cassa ($ chiave, $ direzione = 'asc') dove $ chiave è una proprietà della direzione oggetti e $ è 'asc' o

Opzione 2 'desc': cassa (($ chiave matrice => $ direzione, $ chiave => direzione $)) È simile all'opzione 1, tuttavia, quando 2 oggetti hanno lo stesso valore per $ chiave, viene utilizzata la seconda opzione di ordinamento dall'array passato.

public function order($arr, $key=null, $direction='ASC'){ 
    if(!is_string($key) && !is_array($key)) 
     throw new InvalidArgumentException("order() expects the first parameter to be a valid key or array"); 

    $props = array(); 

    if(is_string($key)) { 
     $props[$key] = strtolower($direction) == 'asc' ? 1 : -1; 
    }else{ 
     $i = count($key); 
     foreach($key as $k => $dir){ 
      $props[$k] = strtolower($dir) == 'asc' ? $i : -($i); 
      $i--; 
     } 
    } 

    usort($arr, function($a, $b) use ($props){ 
     foreach($props as $key => $val){ 
      if($a->$key == $b->$key) continue; 
      return $a->$key > $b->$key ? $val : -($val); 
     } 
     return 0; 
    }); 

    return $arr; 

} 
+0

Bello grazie. – shanebp

+0

Molto gradito :) –

+0

Molto bella piccola funzione. Stavo usando la risposta accettata per le mie esigenze di smistamento (con alcune modifiche personali) e ho deciso di smettere di funzionare dopo un aggiornamento CMS del sito web.Questo mi ha risparmiato un sacco di tempo cercando di eseguire il debug del problema/era. –

Problemi correlati