Я пытаюсь отсортировать многомерный массив по нескольким ключам и понятия не имею, с чего начать. Я посмотрел на uasort, но не совсем понял, как написать функцию для того, что мне нужно.
Мне нужно отсортировать по состоянию, затем по типу события, затем по дате.
Мой массив выглядит так:
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
источник
источник
Ответы:
Тебе нужно
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);
Начиная с PHP 5.5.0:
array_multisort(array_column($mylist, 'event_type'), SORT_DESC, array_column($mylist, 'title'), SORT_ASC, $mylist);
$mylist
сейчас: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', ), )
источник
array_column
функции github.com/ramsey/array_column . Таким образом, можно использовать более элегантный способ из второго фрагмента кода в устаревших версиях.Вы можете сделать это с помощью
usort
.$cmp_function
Аргумент может быть: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']); }
Для произвольного количества полей в PHP 5.3 вы можете использовать замыкания для создания функции сравнения:
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')))
Для произвольного количества полей разных типов в 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')))
источник
PHP7 СУПЕР упрощает сортировку по нескольким столбцам с помощью оператора космического корабля (
<=>
), известного как «Комбинированный оператор сравнения» или «Оператор трехстороннего сравнения».Ресурс: https://wiki.php.net/rfc/combined-comparison-operator
Сортировка по нескольким столбцам так же проста, как запись сбалансированных / реляционных массивов по обе стороны от оператора. Сделано легко!
Я не использовал,
uasort()
потому что не вижу необходимости сохранять исходные индексы.Код: ( Демо )
$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);
Вывод
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 Синтаксис стрелок в PHP7.4 и выше ( Демо ) ...
usort($array, fn($a, $b) => [$a['state'], $a['event_type'], $a['date_start']] <=> [$b['state'], $b['event_type'], $b['date_start']] );
Эквивалентная техника с
array_multisort()
вызовомarray_column()
каждого критерия сортировки: ( Демо )array_multisort( array_column($array, 'state'), array_column($array, 'event_type'), array_column($array, 'date_start'), $array );
источник
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);
источник
Я попытался ввести код ниже, и я успешно
код массива
$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') );
вызов функции сортировки массива
$songs = subval_sort($songs,'artist'); print_r($songs);
функция сортировки массивов
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; }
если функция обратной сортировки массива
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; }
источник
Улучшение гениального кода @Stijn Leenknegt, вот моя прагматическая функция за 2 цента:
$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"]));
источник
if ($diff) { return $diff * ($sortDir === 'asc' ? 1 : -1); }
Может кому поможет:
// data to sort $output = 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') ); // multi column, multi direction order by $body['order_by'] = array( array("field"=> "event_type", "order"=> "desc"), array("field"=> "title", "order"=> "asc"), array("field"=> "ID", "order"=> "asc"), ); $output = $this->multiColumnMultiDirectionSort($body, $output); public function multiColumnMultiDirectionSort(array $body, array $output) { // get order fields and its direction in proper format $orderFieldDirection = []; if (!empty($body['order_by']) && is_array($body['order_by'])) { foreach ($body['order_by'] as $order) { $orderDirection = $order['order'] == "desc" ? SORT_DESC : SORT_ASC; // we need format that array_multisort supports $orderFieldDirection[$order['field']] = $orderDirection; } } if (!empty($orderFieldDirection)) { // get the list of sort columns and their data in the format that is required by array_multisort $amParams = []; $sort = []; foreach ($orderFieldDirection as $field => $order) { foreach ($output as $k => $v) { $sort[$field][$k] = $v[$field]; } $amParams[] = $sort[$field]; $amParams[] = $order; $amParams[] = SORT_REGULAR; // this is not needed, but we can keep as it might come handy in the future } $amParams[] = &$output; // very important to pass as reference call_user_func_array("array_multisort", $amParams); } return $output; }
источник
если вы хотите отсортировать многомерный массив
первый массив:
$results['total_quote_sales_person_wise']['quote_po'];
второй:
$results['total_quote_sales_person_wise']['quote_count'];
этот многомерный массив, который вы хотите отсортировать по убыванию за один раз, затем используйте этот код:
array_multisort($results['total_quote_sales_person_wise']['quote_po'],SORT_DESC, $results['total_quote_sales_person_wise']['quote_count'],SORT_DESC);
источник