Учитывая этот массив:
$inventory = array( array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), array("type"=>"pork", "price"=>5.43), );
Я хотел бы отсортировать элементы $inventory
по цене, чтобы получить:
$inventory = array( array("type"=>"pork", "price"=>5.43), array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), );
Как я могу это сделать?
Вы правы, функция, которую вы ищете, – array_multisort()
.
Вот пример, взятый из руководства и адаптированный к вашему делу:
$price = array(); foreach ($inventory as $key => $row) { $price[$key] = $row['price']; } array_multisort($price, SORT_DESC, $inventory);
Начиная с 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, если справа больше
что именно нужно. Фактически, почти полное обоснование, данное для добавления <=>
на язык https://wiki.php.net/rfc/combined-comparison-operator, заключается в том, что оно
делает заказы на заказы на запись для использования с
usort()
проще
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
, должна возвращать целые числа для usort
работы usort
:
Возвращение нецелых значений из функции сравнения, например float, приведет к внутреннему отбрасыванию до целого числа возвращаемого значения обратного вызова. Таким образом, значения, такие как 0,99 и 0,1, будут приведены к целочисленному значению 0, которое сравнивает такие значения как равные.
Это важная ловушка, которую следует учитывать при использовании usort
в PHP 5.x! Моя первоначальная версия этого ответа допустила эту ошибку, и, тем не менее, я набрал десять вершин над тысячами просмотров, по-видимому, никто не заметил серьезной ошибки. Легкость, с которой такие недостатки, как я, может испортить функции компаратора, является именно тем, что более простой в использовании оператор космического корабля был добавлен к языку в 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 ) )
Я закончил так:
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']); });
В то время как другие правильно предложили использовать array_multisort()
, по какой-то причине ответ, похоже, не подтверждает существование array_column()
, что может значительно упростить решение. Поэтому мое предложение было бы:
array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
$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 .
//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 ) )
Эта функция повторно используется:
function usortarr(&$array, $key, $callback = 'strnatcasecmp') { uasort($array, function($a, $b) use($key, $callback) { return call_user_func($callback, $a[$key], $b[$key]); }); }
Он хорошо работает со строковыми значениями по умолчанию, но вам придется подставить обратный вызов для функции сравнения чисел, если все ваши значения являются числами.
Полная динамическая функция. Я прыгнул сюда для сортировки ассоциативных массивов и нашел эту удивительную функцию на 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
попробуй это:
asort($array_to_sort, SORT_NUMERIC);
для справки см. это: http://php.net/manual/en/function.asort.php
см. различные флаги сортировки здесь: http://www.php.net/manual/en/function.sort.php
$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 ) )
Сортировка массива ассоциативных массивов по значению заданного ключа в php :
$array = array('0'=>array('price'=>'1000.50','product'=>'test1'), '1'=>array('price'=>'8800.50','product'=>'test2'), '2'=>array('price'=>'200.0','product'=>'test3')); function cmp($a, $b) { $p1 = $a['price']; $p2 = $b['price']; return (float)$p1 > (float)$p2; } @uasort($array, "cmp");