Estoy tratando de ordenar una matriz multidimensional por varias claves y no tengo idea de por dónde empezar. Miré uasort, pero no estaba muy seguro de cómo escribir una función para lo que necesito.
Necesito ordenar por estado, luego event_type, luego date.
Mi matriz se ve así:
Array
(
[0] => Array
(
[ID] => 1
[title] => Boring Meeting
[date_start] => 2010-07-30
[time_start] => 06:45:PM
[time_end] =>
[state] => new-york
[event_type] => meeting
)
[1] => Array
(
[ID] => 2
[title] => Find My Stapler
[date_start] => 2010-07-22
[time_start] => 10:45:AM
[time_end] =>
[state] => new-york
[event_type] => meeting
)
[2] => Array
(
[ID] => 3
[title] => Mario Party
[date_start] => 2010-07-22
[time_start] => 02:30:PM
[time_end] => 07:15:PM
[state] => new-york
[event_type] => party
)
[3] => Array
(
[ID] => 4
[title] => Duct Tape Party
[date_start] => 2010-07-28
[time_start] => 01:00:PM
[time_end] =>
[state] => california
[event_type] => party
)
...... etc
php
arrays
sorting
multidimensional-array
attepted_nerd
fuente
fuente
Respuestas:
Necesitas
array_multisort
$mylist = array( array('ID' => 1, 'title' => 'Boring Meeting', 'event_type' => 'meeting'), array('ID' => 2, 'title' => 'Find My Stapler', 'event_type' => 'meeting'), array('ID' => 3, 'title' => 'Mario Party', 'event_type' => 'party'), array('ID' => 4, 'title' => 'Duct Tape Party', 'event_type' => 'party') ); # get a list of sort columns and their data to pass to array_multisort $sort = array(); foreach($mylist as $k=>$v) { $sort['title'][$k] = $v['title']; $sort['event_type'][$k] = $v['event_type']; } # sort by event_type desc and then title asc array_multisort($sort['event_type'], SORT_DESC, $sort['title'], SORT_ASC,$mylist);
A partir de PHP 5.5.0:
array_multisort(array_column($mylist, 'event_type'), SORT_DESC, array_column($mylist, 'title'), SORT_ASC, $mylist);
$mylist
es ahora:array ( 0 => array ( 'ID' => 4, 'title' => 'Duct Tape Party', 'event_type' => 'party', ), 1 => array ( 'ID' => 3, 'title' => 'Mario Party', 'event_type' => 'party', ), 2 => array ( 'ID' => 1, 'title' => 'Boring Meeting', 'event_type' => 'meeting', ), 3 => array ( 'ID' => 2, 'title' => 'Find My Stapler', 'event_type' => 'meeting', ), )
fuente
array_column
función github.com/ramsey/array_column . Por lo tanto, es posible utilizar una forma más elegante del segundo fragmento de código en versiones heredadas.Puedes hacerlo con
usort
. El$cmp_function
argumento podría ser:function my_sorter($a, $b) { $c = strcmp($a['state'], $b['state']); if($c != 0) { return $c; } $c = strcmp($a['event_type'], $b['event_type']); if($c != 0) { return $c; } return strcmp($a['date_start'], $b['date_start']); }
Para un número arbitrario de campos en PHP 5.3, puede usar cierres para crear una función de comparación:
function make_cmp($fields, $fieldcmp='strcmp') { return function ($a, $b) use (&$fields) { foreach ($fields as $field) { $diff = $fieldcmp($a[$field], $b[$field]); if($diff != 0) { return $diff; } } return 0; } } usort($arr, make_cmp(array('state', 'event_type', 'date_start')))
Para un número arbitrario de campos de diferentes tipos en PHP 5.3:
function make_cmp($fields, $dfltcmp='strcmp') { # assign array in case $fields has no elements $fieldcmps = array(); # assign a comparison function to fields that aren't given one foreach ($fields as $field => $cmp) { if (is_int($field) && ! is_callable($cmp)) { $field = $cmp; $cmp = $dfltcmp; } $fieldcmps[$field] = $cmp; } return function ($a, $b) use (&$fieldcmps) { foreach ($fieldcmps as $field => $cmp) { $diff = call_user_func($cmp, $a[$field], $b[$field]); if($diff != 0) { return $diff; } } return 0; } } function numcmp($a, $b) { return $a - $b; } function datecmp($a, $b) { return strtotime($a) - strtotime($b); } /** * Higher priority come first; a priority of 2 comes before 1. */ function make_evt_prio_cmp($priorities, $default_priority) { return function($a, $b) use (&$priorities) { if (isset($priorities[$a])) { $prio_a = $priorities[$a]; } else { $prio_a = $default_priority; } if (isset($priorities[$b])) { $prio_b = $priorities[$b]; } else { $prio_b = $default_priority; } return $prio_b - $prio_a; }; } $event_priority_cmp = make_evt_prio_cmp( array('meeting' => 5, 'party' => 10, 'concert' => 7), 0); usort($arr, make_cmp(array('state', 'event' => $event_priority_cmp, 'date_start' => 'datecmp', 'id' => 'numcmp')))
fuente
PHP7 Hace que la clasificación por múltiples columnas sea SUPER fácil con el operador de nave espacial (
<=>
) también conocido como "Operador de comparación combinado" o "Operador de comparación de tres vías".Recurso: https://wiki.php.net/rfc/combined-comparison-operator
Ordenar por múltiples columnas es tan simple como escribir arreglos balanceados / relacionales en ambos lados del operador. ¡Fácil de hacer!
No lo he usado
uasort()
porque no veo ninguna necesidad de preservar los índices originales.Código: ( Demo )
$array = [ ['ID' => 1, 'title' => 'Boring Meeting', 'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york'], ['ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york'], ['ID' => 3, 'title' => 'Mario Party', 'date_start' => '2010-07-22', 'event_type' => 'party', 'state' => 'new-york'], ['ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party', 'state' => 'california'] ]; usort($array, function($a, $b) { return [$a['state'], $a['event_type'], $a['date_start']] <=> [$b['state'], $b['event_type'], $b['date_start']]; }); var_export($array);
Salida
array ( 0 => array ( 'ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party', 'state' => 'california', ), 1 => array ( 'ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york', ), 2 => array ( 'ID' => 1, 'title' => 'Boring Meeting', 'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york', ), 3 => array ( 'ID' => 3, 'title' => 'Mario Party', 'date_start' => '2010-07-22', 'event_type' => 'party', 'state' => 'new-york', ), )
ps Arrow sintaxis con PHP7.4 y superior ( Demo ) ...
usort($array, fn($a, $b) => [$a['state'], $a['event_type'], $a['date_start']] <=> [$b['state'], $b['event_type'], $b['date_start']]);
fuente
class Sort { private $actual_order = 'asc'; private $actual_field = null; public function compare_arrays($array1, $array2) { if ($array1[$this->actual_field] == $array2[$this->actual_field]) { return 0; } elseif ($array1[$this->actual_field] > $array2[$this->actual_field]) { return ($this->actual_order == 'asc' ? 1 : -1); } else { return ($this->actual_order == 'asc' ? -1 : 1); } } public function order_array(&$array) { usort($array, array($this, 'compare_arrays')); } public function __construct ($field, $actual_order = 'asc') { $this->actual_field = $field; $this->actual_order = $actual_order; } } // use $sort = new Sort ("state"); $sort->order_array($array);
fuente
Intenté el siguiente código y lo logré
código de matriz
$songs = array( '1' => array('artist'=>'Smashing Pumpkins', 'songname'=>'Soma'), '2' => array('artist'=>'The Decemberists', 'songname'=>'The Island'), '3' => array('artist'=>'Fleetwood Mac', 'songname' =>'Second-hand News') );
llamar a la función de clasificación de matriz
$songs = subval_sort($songs,'artist'); print_r($songs);
función de clasificación de matriz
function subval_sort($a,$subkey) { foreach($a as $k=>$v) { $b[$k] = strtolower($v[$subkey]); } asort($b); foreach($b as $key=>$val) { $c[] = $a[$key]; } return $c; }
si la función de clasificación inversa de matriz
function subval_sort($a,$subkey) { foreach($a as $k=>$v) { $b[$k] = strtolower($v[$subkey]); } arsort($b); foreach($b as $key=>$val) { $c[] = $a[$key]; } return $c; }
fuente
Mejorando el código genio de @Stijn Leenknegt, aquí está mi función pragmática de 2 centavos:
$data[] = array('volume' => 67, 'edition' => 2); $data[] = array('volume' => 86, 'edition' => 1); $data[] = array('volume' => 85, 'edition' => 6); $data[] = array('volume' => 98, 'edition' => 2); $data[] = array('volume' => 86, 'edition' => 6); $data[] = array('volume' => 67, 'edition' => 7); function make_cmp(array $sortValues) { return function ($a, $b) use (&$sortValues) { foreach ($sortValues as $column => $sortDir) { $diff = strcmp($a[$column], $b[$column]); if ($diff !== 0) { if ('asc' === $sortDir) { return $diff; } return $diff * -1; } } return 0; }; } usort($data, make_cmp(['volume' => "desc", 'edition' => "asc"]));
fuente
si desea ordenar una matriz multidimensional
la primera matriz es:
$results['total_quote_sales_person_wise']['quote_po'];
el segundo es:
$results['total_quote_sales_person_wise']['quote_count'];
esta matriz multidimensional que desea ordenar en orden descendente a la vez, luego use este código:
array_multisort($results['total_quote_sales_person_wise']['quote_po'],SORT_DESC, $results['total_quote_sales_person_wise']['quote_count'],SORT_DESC);
fuente