给定这个数组:
$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 5.5.0 开始,您可以使用 array_column()
代替 foreach:
$price = array_column($inventory, 'price');
array_multisort($price, SORT_DESC, $inventory);
PHP 7+
从 PHP 7 开始,这可以通过使用 usort
和使用 spaceship operator 比较元素的 anonymous function 来简洁地完成。
您可以像这样进行升序排序:
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 引入了匿名函数,但还没有 spaceship 运算符。我们仍然可以使用 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
正常工作:
从比较函数返回非整数值,例如浮点数,将导致内部强制转换为回调返回值的整数。因此,诸如 0.99 和 0.1 之类的值都将被转换为整数值 0,这将比较这些值是否相等。
这是在 PHP 5.x 中使用 usort
时要牢记的一个重要陷阱! My original version of this answer 犯了这个错误,但我显然在没有人注意到这个严重错误的情况下,在数千次观看中获得了 10 次赞成票。 正是,像我这样的笨蛋可以轻松搞砸比较器函数,这正是 PHP 7 中将更易于使用的 spaceship 运算符添加到语言中的原因。
uasort
。但是,在查看文档后,这个答案仍然是正确的在这种情况下。在 OP 的示例中,要排序的数组具有顺序数字索引而不是字符串索引,因此 usort
更合适。在按顺序索引的数组上使用 uasort
将导致排序后的数组不按其数字索引排序,因此在 foreach
循环中看到的第一个元素不是 $your_array[0]
,这不太可能是理想的行为.
虽然其他人正确建议使用 array_multisort()
,但由于某种原因,似乎没有答案承认 array_column()
的存在,这可以大大简化解决方案。所以我的建议是:
array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
如果您想对字符串进行不区分大小写排序,可以使用 SORT_NATURAL|SORT_FLAG_CASE
array_multisort(array_column($inventory, 'key_name'), SORT_DESC, SORT_NATURAL|SORT_FLAG_CASE, $inventory);
由于您的数组元素本身就是带有字符串键的数组,因此最好的办法是定义一个自定义比较函数。这是非常快速和容易做到的。尝试这个:
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
)
)
uasort( $inventory, function ($a, $b) { if ( $a==$b ) return 0; else return ($a > $b) ? -1 : 1; });
usort
似乎比 uasort
更适合使用顺序数字键对数组进行排序。以第一个元素位于索引 1
而第二个元素位于索引 0
的数组结尾是一种奇怪的行为,对于不熟悉 PHP 数组细节的人来说无疑是一个陷阱; usort
为您提供直观期望的输出。
我结束了这个:
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');
从 Sort an array of associative arrays by value of given key in php:
通过使用 usort (http://php.net/usort) ,我们可以按升序和降序对数组进行排序。只是我们需要创建一个函数并将其作为参数传递给 usort。根据下面的示例,如果我们通过小于条件,则大于用于升序,则它按降序排序。例子 :
$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'];
}
usort($array, "cmp");
print_r($array);
输出:
Array
(
[0] => Array
(
[price] => 200.0
[product] => test3
)
[1] => Array
(
[price] => 1000.50
[product] => test1
)
[2] => Array
(
[price] => 8800.50
[product] => test2
)
)
cmp
函数是错误的。它应该返回 “如果第一个参数被认为分别小于、等于或大于第二个参数,则它是一个小于、等于或大于零的整数”,而是返回 {2 } 或 false
。值得注意的是,它似乎仍然有效 - 也许是因为 usort
和朋友的当前实现同样对待“小于”和“等于”情况 - 但不要指望它在未来的 PHP 版本中继续工作。如果他们试图使排序稳定(即不要不必要地围绕相等的元素移动),这将中断。
usort
比 uasort
更合适,因为 uasort
保留了键和值之间的关联,这在处理顺序数字数组时会令人困惑和意外。例如,调用 uasort
后的上述 $array
的索引依次为 2、0 和 1。除非出于某种原因需要,否则使用 usort
可能会更舒服,它会重新索引数组并对其重新排序。
$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
适用于 PHP 7 及更高版本。
/**
* A method for sorting associative arrays by a key and a direction.
* Direction can be ASC or DESC.
*
* @param $array
* @param $key
* @param $direction
* @return mixed $array
*/
function sortAssociativeArrayByKey($array, $key, $direction){
switch ($direction){
case "ASC":
usort($array, function ($first, $second) use ($key) {
return $first[$key] <=> $second[$key];
});
break;
case "DESC":
usort($array, function ($first, $second) use ($key) {
return $second[$key] <=> $first[$key];
});
break;
default:
break;
}
return $array;
}
用法:
$inventory = sortAssociativeArrayByKey($inventory, "price", "ASC");
我像这样使用 uasort
<?php
$users = [
[
'username' => 'joe',
'age' => 11
],
[
'username' => 'rakoto',
'age' => 21
],
[
'username' => 'rabe',
'age' => 17
],
[
'username' => 'fy',
'age' => 19
],
];
uasort($users, function ($item, $compare) {
return $item['username'] >= $compare['username'];
});
var_dump($users);
在 100 000 条记录上进行了测试:以秒为单位的时间(由功能微时间计算)。仅用于排序关键位置的唯一值。
@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*
}
尝试这个:
$prices = array_column($inventory, 'price');
array_multisort($prices, SORT_DESC, $inventory);
print_r($inventory);
此功能可重复使用:
function usortarr(&$array, $key, $callback = 'strnatcasecmp') {
uasort($array, function($a, $b) use($key, $callback) {
return call_user_func($callback, $a[$key], $b[$key]);
});
}
默认情况下,它适用于字符串值,但如果您的所有值都是数字,则必须将回调子用于 number comparison function。
usortarr
,但随后调用 uasort
而不是 usort
;也许有点混乱。后者是 - 在具有数字索引的顺序数组的情况下,就像问题中展示的那样 - 可能是您真正想要的。
您可以尝试定义自己的比较函数,然后使用 usort。
这是我很久以前发现并清理了一下的方法。这很好用,并且可以快速更改以接受对象。
/**
* A method for sorting arrays by a certain key:value.
* SortByKey is the key you wish to sort by
* Direction can be ASC or DESC.
*
* @param $array
* @param $sortByKey
* @param $sortDirection
* @return array
*/
private function sortArray($array, $sortByKey, $sortDirection) {
$sortArray = array();
$tempArray = array();
foreach ( $array as $key => $value ) {
$tempArray[] = strtolower( $value[ $sortByKey ] );
}
if($sortDirection=='ASC'){ asort($tempArray ); }
else{ arsort($tempArray ); }
foreach ( $tempArray as $key => $temp ){
$sortArray[] = $array[ $key ];
}
return $sortArray;
}
要更改对对象进行排序的方法,只需更改以下行:
$tempArray[] = strtolower( $value[ $sortByKey ] );
到 $tempArray[] = strtolower( $value->$sortByKey );
要运行该方法,只需执行
sortArray($inventory,'price','ASC');
array_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
)
)
自 PHP 7.4 起,您可以使用箭头函数:
usort(
$inventory,
fn(array $a, array $b): int => $b['price'] <=> $a['price']
);
代码 (demo):
$inventory = [
['type' => 'fruit', 'price' => 3.50],
['type' => 'milk', 'price' => 2.90],
['type' => 'pork', 'price' => 5.43],
];
usort(
$inventory,
fn(array $a, array $b): int => $b['price'] <=> $a['price']
);
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)
)
完整的动态函数我跳到这里进行关联数组排序,并在 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
如果您需要对具有不同大小写的字符串数组进行排序,这会将排序数组值更改为小写。
$data = [
[
'name' => 'jack',
'eyeColor' => 'green'
],
[
'name' => 'Amy',
'eyeColor' => 'brown'
],
[
'name' => 'Cody',
'eyeColor' => 'blue'
]
];
function toLowerCase($a) { return strtolower($a); }
$sortArray = array_map("toLowerCase",array_column($data, 'name'));
array_multisort($sortArray, SORT_ASC, $data);
此功能在所有主要版本的 PHP 上 100% 工作,并且已使用 PHP5、PHP7、PHP8 进行了测试。
function sort_my_array($array, $order_by, $order)
{
switch ($order) {
case "asc":
usort($array, function ($first, $second) use ($order_by) {
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
return $first[$order_by] <=> $second[$order_by];
} else {
$array_cmp = strcmp($first[$order_by], $second[$order_by]);
return $array_cmp ;
}
});
break;
case "desc":
usort($certificates, function ($first, $second) use ($order_by) {
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
return $first[$order_by] <=> $second[$order_by];
} else {
$array_cmp = strcmp($first[$order_by], $second[$order_by]);
return -$array_cmp ;
}
});
break;
default:
break;
}
return $array;
}
许多人正在寻找一种方法来使用 Laravel 做到这一点并最终来到这里。此外,由于这个问题的重复,一些 Laravel 问题正在关闭。因此,我分享了一种使用 Laravel collect() 方法执行它的简单方法。
$inventory = collect($inventory)->sortBy('price')->toArray();
对于降序
$inventory = collect($inventory)->sortBy('price')->reverse()->toArray();
或者,
$inventory = collect($inventory)->('price')->reverse()->toArray();
$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;
}
尝试这个:
asort($array_to_sort, SORT_NUMERIC);
供参考,请参阅:http://php.net/manual/en/function.asort.php
在此处查看各种排序标志:http://www.php.net/manual/en/function.sort.php
不定期副业成功案例分享