2010-03-11 1 views
12

Supponiamo di disporre di un array che simula una tabella di database. Ogni elemento dell'array rappresenta una riga e all'interno di ogni riga c'è un altro array che contiene i nomi e i valori dei campi.Come ordinare un array multidimensionale in uno dei campi dell'array interno in PHP?

Array 
(
    [0] => Array 
     (
      [name] => 'Sony TV' 
      [price] => 600.00 
     ) 

    [1] => Array 
     (
      [name] => 'LG TV' 
      [price] => 350.00 
     ) 

    [2] => Array 
     (
      [name] => 'Samsung TV' 
      [price] => 425.00 
     ) 
} 

Quello che voglio fare è ordinare le righe (elementi dell'array esterno) in base al prezzo. Di seguito è riportato un esempio di quello che voglio ottenere:

Array 
(
    [0] => Array 
     (
      [name] => 'LG TV' 
      [price] => 350.00 
     ) 

    [1] => Array 
     (
      [name] => 'Samsung TV' 
      [price] => 425.00 
     ) 

    [2] => Array 
     (
      [name] => 'Sony TV' 
      [price] => 600.00 
     )   
} 

Come potete vedere, non ho bisogno di conservare le chiavi della matrice esterna.

+0

Nota: se i dati provengono da un database, utilizzare i metodi di ordinamento del database durante la selezione. – DisgruntledGoat

+0

Duplicato: http://stackoverflow.com/questions/2122062/sort-multidimensional-array-of-objects –

+0

@DisgruntledGoat Non proviene da un database. L'ho usato solo come esempio. In realtà sta arrivando da un XML di terze parti. – Camsoft

risposta

23

È necessario utilizzare usort, una funzione che ordina gli array tramite una funzione definita dall'utente. Qualcosa di simile:

function cmp($a, $b) 
{ 
    if ($a["price"] == $b["price"]) { 
     return 0; 
    } 
    return ($a["price"] < $b["price"]) ? -1 : 1; 
} 

usort($yourArray,"cmp") 
10

È possibile utilizzare usort():

function sort($a, $b) { 
    if ($a['price'] == $b['price']) return 0; 
    return ($a['price'] > $b['price']) ? 1 : -1; 
} 

usort($array, 'sort'); 

Ancora meglio se si crea una classe come questo per riutilizzare il codice:

class FieldSorter { 
    public $field; 

    function __construct($field) { 
     $this->field = $field; 
    } 

    function cmp($a, $b) { 
     if ($a[$this->field] == $b[$this->field]) return 0; 
     return ($a[$this->field] > $b[$this->field]) ? 1 : -1; 
    } 
} 

$sorter = new FieldSorter('price');  
usort($array, array($sorter, "cmp")); 

In questo modo, puoi facilmente ordina per altri campi.

E sebbene tu abbia detto che i tasti dell'array esterno non devono essere conservati, puoi facilmente ottenere ciò usando uasort() invece di usort.

+1

Il suggerimento di classe è fantastico! – MastaBaba

1

Questa domanda è un po 'vecchia, ma lascerà la risposta qui per il futuro.

Dalla funzione php.net-Multisort è possibile utilizzare il seguente codice;

$data= [['volume' => 67, 'edition' => 2],['volume' => 85, 'edition' => 6],...]; 
foreach ($data as $key => $row) { 
    $volume[$key] = $row['volume']; 
    $edition[$key] = $row['edition']; 
} 
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data); 

Quanto sopra è per un ordinamento statico dei dati in cui si modificano manualmente le colonne di ordinamento.

Per un esempio più dinamico e robusto, considerare di seguito;

Si supponga di avere i seguenti dati;

$data = [[1, 'Amanda', 'Wright', '[email protected]', 'Female', '135.114.57.89', 31237], 
      [2, 'Theresa', 'Larson', '[email protected]', 'Female', '207.108.96.210', 91011], 
      [3, 'Walter', 'Kennedy', '[email protected]', 'Male', '199.147.223.56', 50114], 
      [4, 'Andrea', 'Richards', '[email protected]', 'Female', '230.195.124.95', 76489], 
      [5, 'Carol', 'Jones', '[email protected]', 'Female', '250.197.111.90', 56501], 
      [6, 'Alice', 'Freeman', '[email protected]', 'Female', '52.195.252.131', 77170], 
      [7, 'Gerald', 'Fisher', '[email protected]', 'Male', '81.2.22.62', 75625],....] 

Se dobbiamo ordinare i dati di matrice sopra fuori dalla scatola, quindi possiamo impostare i criteri di ordinamento in una matrice utilizzando la sintassi;

$qTable[$index]=$sort_order; 
E.g. $qTable=[1=>'asc',4=>'desc',3=>'asc']; 

Ciò significa ordinare la colonna 1 ASC, la colonna 4 DESC quindi la colonna 3 ASC. Possiamo quindi utilizzare la funzione seguente per ordinare i dati del nostro database multidimensionale;

function sortMulti($data, $orders) 
    { 
     $args = []; 
     foreach ($data as $key => $row) { 
      foreach ($orders as $index => $order) { 
       if (!isset($row[$index])) continue; //Ignore if column does'nt exist 
       $args[$index]['d'][$key] = $row[$index]; //Get all values within the column 
       $args[$index]['o']  = 'desc' == strtolower($order) ? SORT_DESC : SORT_ASC; //Get the Sort order 'ASC' is the default 
      } 
     } 
     $p = []; 
//Below we need to organize our entries as arguments for array_multisort 
     foreach ($args as $arg) { 
      $p[] = $arg['d']; 
      $p[] = $arg['o']; 
//Below we need to check if column contains only numeric or not. 
//If all values are numeric, then we use numeric sort flag, otherwise NATURAL 
//Manipulate for more conditions supported 
      $p[] = count($arg['d']) == count(array_filter($arg['d'], 'is_numeric')) ? SORT_NUMERIC : SORT_NATURAL; 
     } 
     $p[] = &$data; //Pass by reference 
     call_user_func_array('array_multisort', $p); //Call Php's own multisort with parameters in required order. 
     return $data; //Our final array sorted. 
    } 

Quindi possiamo usarlo come di seguito;

$data=[[...],[...],...]; 
$order=[1=>'asc',4=>'desc',3=>'asc']; 

$sorted=sortMulti($data,$order); 

Per valori chiave dati dell'array E.g. $data=[['c1'=>1212,'c2'=>'mynames'],...]; Utilizzare l'ordine come $order=['c1'=>'desc','c10'=>'asc'];

ho provato quanto sopra con una serie di 1000 record. Spero che aiuti qualcuno.

+0

Bello che funzioni anche con chiavi non numeriche –

0

Un'alternativa a usort consiste nel creare un array che indicizza l'array che si desidera ordinare e viene indicizzato dai dati che si desidera ordinare.

Nel frammento di seguito, $ CustomAttributes è un array di oggetti che vorrei per ordinare per nome . Il primo $ ordinamento viene creato, indicizzato da nome e contenente l'indice di array dell'elemento $ customAttributes corrispondente.

$sort = []; 
foreach($customAttributes as $c => $ca) 
{ 
    $sort[$ca->name] = $c; 
} 

ksort viene quindi utilizzato per ordinare l'array chiave.

ksort($sort); 

Una volta che l'array $ sorta è stato ordinato, scorrere e creare il $ ordinato serie .

$ordered = []; 
foreach($sort as $s) 
{ 
    $ordered[] = $customAttributes[$s]; 
} 

Mi piace questa soluzione perché ci sono meno chiamate di funzione rispetto all'utilizzo di callback.

0

È possibile creare una funzione di se stessi come quella qui sotto

funzione orderArrayBycolumn privato ($ array, $ colonna) {

$newArray = []; 
    foreach ($array as $key => $value) { 
     $newArray[$value[$column]] = $value; 
    } 

    $array = []; 

    ksort($newArray); 

    foreach ($newArray as $key => $value) { 
     $array[] = $value; 
    }  

    return $array; 
}