给定这个数组:
$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),
);
我该怎么做呢?
对10万条记录进行了测试:
时间单位为秒(由函数微时间计算)。
仅用于对键位置进行排序时的唯一值。
@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*
}
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中将更容易使用的宇宙飞船操作符添加到语言中的原因。
完整的动态功能
我跳到这里进行关联数组排序,并在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