Как отсортировать массив ассоциативных массивов по значению заданного ключа в PHP?

Учитывая этот массив:

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

Как я могу это сделать?

Solutions Collecting From Web of "Как отсортировать массив ассоциативных массивов по значению заданного ключа в PHP?"

Вы правы, функция, которую вы ищете, – 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, если справа больше

что именно нужно. Фактически, почти полное обоснование, данное для добавления <=> на язык 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 , должна возвращать целые числа для 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");