给定这个数组:

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

);

我该怎么做呢?


当前回答

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。+。

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的整数值,这将把这两个值作为相等进行比较。

这是在PHP 5.x中使用usort时要记住的一个重要陷阱!我最初的答案就犯了这个错误,但我在没有人注意到这个严重的错误的情况下,获得了成千上万的点赞。像我这样的弱智很容易搞砸比较器函数,这正是在PHP 7中将更容易使用的宇宙飞船操作符添加到语言中的原因。

其他回答

许多人都在寻找一种方法来做Laravel,并最终在这里结束。此外,一些Laravel问题由于这个问题的重复而被关闭。 因此,我分享了一种使用Laravel collect()方法执行它的简单方法。

$inventory = collect($inventory)->sortBy('price')->toArray();

降序排列

$inventory = collect($inventory)->sortBy('price')->reverse()->toArray();

Or,

$inventory = collect($inventory)->('price')->reverse()->toArray();

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。+。

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的整数值,这将把这两个值作为相等进行比较。

这是在PHP 5.x中使用usort时要记住的一个重要陷阱!我最初的答案就犯了这个错误,但我在没有人注意到这个严重的错误的情况下,获得了成千上万的点赞。像我这样的弱智很容易搞砸比较器函数,这正是在PHP 7中将更容易使用的宇宙飞船操作符添加到语言中的原因。

这个函数是可重用的:

function usortarr(&$array, $key, $callback = 'strnatcasecmp') {
    uasort($array, function($a, $b) use($key, $callback) {
        return call_user_func($callback, $a[$key], $b[$key]);
    });
}

默认情况下,它在字符串值上工作得很好,但如果所有值都是数字,则必须为数字比较函数指定子回调函数。

虽然其他人正确地建议使用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);

从PHP 7.4开始,你可以使用arrow函数:

usort(
    $inventory, 
    fn(array $a, array $b): int => $b['price'] <=> $a['price']
);

代码(演示):

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