2010-03-11 9 views
12

Supongamos que tengo una matriz que imita una tabla de base de datos. Cada elemento de matriz representa una fila, y dentro de cada fila hay otra matriz que contiene los nombres y valores de campo.¿Cómo puedo ordenar una matriz multidimensional por uno de los campos de la matriz interna en 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 
     ) 
} 

Lo que quiero hacer es ordenar las filas (elementos de la matriz externa) por precio. A continuación se muestra un ejemplo de lo que quiero lograr:

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

Como se puede ver, no necesito para preservar las claves de la matriz externa.

+0

Nota: Si sus datos provienen de una base de datos, utilice los métodos de clasificación de la base de datos al seleccionar. – DisgruntledGoat

+0

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

+0

@DisgruntledGoat No proviene de una base de datos. Acabo de usar eso como un ejemplo. En realidad viene de un XML de terceros. – Camsoft

Respuesta

23

Necesita usar usort, una función que ordena las matrices a través de una función definida por el usuario. Algo así como:

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

usort($yourArray,"cmp") 
10

Puede utilizar usort():

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

usort($array, 'sort'); 

Aún mejor si se crea una clase como esta para reutilizar el código:

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")); 

De esta manera, puede fácilmente ordenar por otros campos.

Y aunque haya dicho que las teclas de la matriz externa no tienen que conservarse, puede lograrlo fácilmente usando uasort() en lugar de usort.

+1

¡La sugerencia de la clase es asombrosa! – MastaBaba

1

Esta pregunta es un poco antigua, pero dejará la respuesta aquí para el futuro.

Desde php.net-Multisort función podemos utilizar el siguiente código;

$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); 

Lo anterior es para una clasificación estática de datos donde se cambian manualmente las columnas de clasificación.

Para un ejemplo más dinámico y robusto considere a continuación;

Supongamos que tengo los datos a continuación;

$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],....] 

Si necesitamos para ordenar los datos de la matriz por encima de la caja, entonces podemos establecer los criterios de ordenación en una matriz usando la sintaxis;

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

Esto significa ordenar la columna 1 ASC, la columna 4 DESC y la columna 3 ASC. Podemos entonces usar la función siguiente para ordenar nuestros datos de base de datos multidimensionales;

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

Entonces podemos usarlo como a continuación;

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

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

Para datos de la matriz de valores de claves E.g. $data=[['c1'=>1212,'c2'=>'mynames'],...]; Use la orden como $order=['c1'=>'desc','c10'=>'asc'];

Probé lo anterior con una matriz de 1000 registros. Espero que ayude a alguien.

+0

Agradable que esto funcione con teclas no numéricas también –

0

Una alternativa a usort es crear una matriz que indexa la matriz que desea ordenar y está indexada por los datos que desea ordenar.

En el siguiente fragmento, $ CustomAttributes es una matriz de objetos que me gustaría para ordenar por nombre . Primero $ sort se crea, indexado por nombre y que contiene el índice de matriz del elemento correspondiente $ customAttributes.

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

ksort se utiliza entonces para ordenar la matriz por clave.

ksort($sort); 

Una vez que la matriz $ especie ha sido solucionado, iterar a través de él y crear la $ ordenada matriz.

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

Me gusta esta solución porque hay menos llamadas de función que el uso de devoluciones de llamada.

0

Puede crear una función a sí mismo como la siguiente

orderArrayBycolumn privada de función ($ matriz, la columna $) {

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

    $array = []; 

    ksort($newArray); 

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

    return $array; 
} 
Cuestiones relacionadas