Как отсортировать массив ассоциативных массивов по значению заданного ключа в PHP?
учитывая этот массив:
$inventory = array(
array("type"=>"fruit", "price"=>3.50),
array("type"=>"milk", "price"=>2.90),
array("type"=>"pork", "price"=>5.43),
);
Я хочу вроде по цене для:
$inventory = array(
array("type"=>"pork", "price"=>5.43),
array("type"=>"fruit", "price"=>3.50),
array("type"=>"milk", "price"=>2.90),
);
как я могу это сделать?
16 ответов:
вы правы, функция, которую вы ищете, это
array_multisort().вот пример, взятый прямо из руководства и адаптировать к вашему случаю:
$price = array(); foreach ($inventory as $key => $row) { $price[$key] = $row['price']; } array_multisort($price, SORT_DESC, $inventory);
PHP 7+
начиная с PHP 7, это можно сделать лаконично с помощью
usortС анонимная функция использует оператор космический корабль для сравнения элементов.вы можете сделать восходящую сортировку следующим образом:
usort($inventory, function ($item1, $item2) { return $item1['price'] <=> $item2['price']; });или по убыванию такой:
usort($inventory, function ($item1, $item2) { return $item2['price'] <=> $item1['price']; });чтобы понять, как это работает, обратите внимание, что
usortпринимает предоставленную пользователем функцию сравнения, которая должна вести себя следующим образом (из документов):функция сравнения должна возвращать целое, которое меньше, равно или больше нуля, если первый аргумент является соответственно меньшим, равным или большим чем второй.
и обратите внимание, что
<=>оператор космолет,возвращает 0, если оба операнда равны, 1, если левый больше, и 1, если справа больше
именно что
usortпотребности. На самом деле, почти все обоснование приведено для добавления<=>к языку в https://wiki.php.net/rfc/combined-comparison-operator неужели этоделает запись заказа обратных вызовов для использования с
usort()легче
PHP 5.3+
PHP 5.3 ввел анонимные функции, но еще не имеет оператора космического корабля. Мы все еще можем использовать
usortчтобы отсортировать наш массив, но это немного более многословно и труднее понять:usort($inventory, function ($item1, $item2) { if ($item1['price'] == $item2['price']) return 0; return $item1['price'] < $item2['price'] ? -1 : 1; });обратите внимание, что хотя это довольно часто для компараторов, имеющих дело с целочисленными значениями, чтобы просто вернуть разницу значений, как
$item2['price'] - $item1['price'], мы не могу безопасно сделать это в этом случае. Это связано с тем, что цены являются числами с плавающей запятой в примере вопроса Аскера, но функцию сравнения мы передаем вusortдолжен возвращать целые числа дляusortработу:возвращение нецелым значения из функции сравнения, такие как float, приведут к внутреннему приведению к целому числу возвращаемого значения обратного вызова. Таким образом, такие значения, как 0.99 и 0.1, будут приведены к целочисленному значению 0, которое будет сравнивать такие значения как равные.
это важная ловушка, чтобы иметь в виду при использовании
usortв PHP 5.х! моя оригинальная версия этого ответа сделал эту ошибку, и все же я набрал десять голосов более тысячи просмотров, по-видимому, никто не заметил серьезной ошибки. Легкость, с которой такие тупицы, как я, могут испортить функции компаратора,точно причина в том, что более простой в использовании оператор космического корабля был добавлен в язык PHP 7.
function invenDescSort($item1,$item2) { if ($item1['price'] == $item2['price']) return 0; return ($item1['price'] < $item2['price']) ? 1 : -1; } usort($inventory,'invenDescSort'); print_r($inventory);производит следующим образом:
Array ( [0] => Array ( [type] => pork [price] => 5.43 ) [1] => Array ( [type] => fruit [price] => 3.5 ) [2] => Array ( [type] => milk [price] => 2.9 ) )
в то время как другие правильно предложил использовать
array_multisort(), по какой-то причине ни один ответ, кажется, не признает существованиеarray_column(), который может значительно упростить решение. Поэтому мое предложение было бы:array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
Я закончил на этом:
function sort_array_of_array(&$array, $subfield) { $sortarray = array(); foreach ($array as $key => $row) { $sortarray[$key] = $row[$subfield]; } array_multisort($sortarray, SORT_ASC, $array); }просто вызовите функцию, передав массив и имя поля массива второго уровня. Например:
sort_array_of_array($inventory, 'price');
можно использовать
usortС анонимной функции, например,usort($inventory, function ($a, $b) { return strnatcmp($a['price'], $b['price']); });
$inventory = array(array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), array("type"=>"pork", "price"=>5.43), ); function pricesort($a, $b) { $a = $a['price']; $b = $b['price']; if ($a == $b) return 0; return ($a > $b) ? -1 : 1; } usort($inventory, "pricesort"); // uksort($inventory, "pricesort"); print("first: ".$inventory[0]['type']."\n\n"); // for usort(): prints milk (item with lowest price) // for uksort(): prints fruit (item with key 0 in the original $inventory) // foreach prints the same for usort and uksort. foreach($inventory as $i){ print($i['type'].": ".$i['price']."\n"); }выходы:
first: pork pork: 5.43 fruit: 3.5 milk: 2.9
был протестирован на 100 000 записей: Время в секундах (вычисляется по funciton microtime). только для уникальных значений при сортировке ключевых позиций.
решение функции @Josh Davis: провели время: 1.5768740177155
мое решение: провели время: 0.094044923782349
устранение:
function SortByKeyValue($data, $sortKey, $sort_flags=SORT_ASC) { if (empty($data) or empty($sortKey)) return $data; $ordered = array(); foreach ($data as $key => $value) $ordered[$value[$sortKey]] = $value; ksort($ordered, $sort_flags); return array_values($ordered); *// array_values() added for identical result with multisort* }
вы можете попытаться определить свою собственную функцию сравнения, а затем использовать usort.
эта функция может использоваться повторно:
function usortarr(&$array, $key, $callback = 'strnatcasecmp') { uasort($array, function($a, $b) use($key, $callback) { return call_user_func($callback, $a[$key], $b[$key]); }); }Он хорошо работает на строковых значениях по умолчанию, но вам придется подменить обратный вызов для функция сравнения если все значения являются числами.
С Сортировать массив ассоциативных массивов по значению данного ключа в php:
uasort (http://php.net/uasort) позволяет сортировать массив по вашей собственной определенной функции. В вашем случае, это просто:
$array = array( array('price'=>'1000.50','product'=>'test1'), array('price'=>'8800.50','product'=>'test2'), array('price'=>'200.0','product'=>'test3') ); function cmp($a, $b) { return $a['price'] > $b['price']; } uasort($array, "cmp");
//Just in one line custom function function cmp($a, $b) { return (float) $a['price'] < (float)$b['price']; } @uasort($inventory, "cmp"); print_r($inventory); //result Array ( [2] => Array ( [type] => pork [price] => 5.43 ) [0] => Array ( [type] => fruit [price] => 3.5 ) [1] => Array ( [type] => milk [price] => 2.9 ) )
Полная Динамическая Функция Я прыгнул сюда для сортировки ассоциативного массива и нашел эту удивительную функцию на http://php.net/manual/en/function.sort.php. эта функция очень динамична, что сортировка в порядке возрастания и убывания с указанным ключом.
простая функция для сортировки массива по определенным ключам. Поддерживает индекс ассоциации
<?php function array_sort($array, $on, $order=SORT_ASC) { $new_array = array(); $sortable_array = array(); if (count($array) > 0) { foreach ($array as $k => $v) { if (is_array($v)) { foreach ($v as $k2 => $v2) { if ($k2 == $on) { $sortable_array[$k] = $v2; } } } else { $sortable_array[$k] = $v; } } switch ($order) { case SORT_ASC: asort($sortable_array); break; case SORT_DESC: arsort($sortable_array); break; } foreach ($sortable_array as $k => $v) { $new_array[$k] = $array[$k]; } } return $new_array; } $people = array( 12345 => array( 'id' => 12345, 'first_name' => 'Joe', 'surname' => 'Bloggs', 'age' => 23, 'sex' => 'm' ), 12346 => array( 'id' => 12346, 'first_name' => 'Adam', 'surname' => 'Smith', 'age' => 18, 'sex' => 'm' ), 12347 => array( 'id' => 12347, 'first_name' => 'Amy', 'surname' => 'Jones', 'age' => 21, 'sex' => 'f' ) ); print_r(array_sort($people, 'age', SORT_DESC)); // Sort by oldest first print_r(array_sort($people, 'surname', SORT_ASC)); // Sort by surname
$arr1 = array( array('id'=>1,'name'=>'aA','cat'=>'cc'), array('id'=>2,'name'=>'aa','cat'=>'dd'), array('id'=>3,'name'=>'bb','cat'=>'cc'), array('id'=>4,'name'=>'bb','cat'=>'dd') ); $result1 = array_msort($arr1, array('name'=>SORT_DESC); $result2 = array_msort($arr1, array('cat'=>SORT_ASC); $result3 = array_msort($arr1, array('name'=>SORT_DESC, 'cat'=>SORT_ASC)); function array_msort($array, $cols) { $colarr = array(); foreach ($cols as $col => $order) { $colarr[$col] = array(); foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); } } $eval = 'array_multisort('; foreach ($cols as $col => $order) { $eval .= '$colarr[\''.$col.'\'],'.$order.','; } $eval = substr($eval,0,-1).');'; eval($eval); $ret = array(); foreach ($colarr as $col => $arr) { foreach ($arr as $k => $v) { $k = substr($k,1); if (!isset($ret[$k])) $ret[$k] = $array[$k]; $ret[$k][$col] = $array[$k][$col]; } } return $ret; }
<?php $inventory = array( array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), array("type"=>"pork", "price"=>5.43), ); function myfunc($a,$b){ return strnatcmp($a['price'],$b['price']); } $result=usort ($inventory,"myfunc");?> <pre><?php print_r(array_reverse($inventory)); ?></pre>самое простое решение :)
выход есть
Array ( [0] => Array ( [type] => pork [price] => 5.43 ) [1] => Array ( [type] => fruit [price] => 3.5 ) [2] => Array ( [type] => milk [price] => 2.9 ) )
попробуйте это:
asort($array_to_sort, SORT_NUMERIC);для справки см. В этом: http://php.net/manual/en/function.asort.php
смотрите различные флаги сортировки здесь: http://www.php.net/manual/en/function.sort.php
Comments