如何在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),


);

我该怎么做呢?

701931 次浏览

您可以尝试定义自己的比较函数,然后使用的作用

试试这个:

asort($array_to_sort, SORT_NUMERIC);

参考如下: # EYZ0 < / p >

在这里看到各种排序标志: # EYZ0 < / p >

$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

因为数组元素本身就是带有字符串键的数组,所以最好定义一个自定义比较函数。做起来又快又简单。试试这个:

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
)


)

你是对的,你要找的函数是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);

我的结尾是这样的:

function sort_array_of_array(&$array, $subfield)
{
$sortarray = array();
foreach ($array as $key => $row)
{
$sortarray[$key] = $row[$subfield];
}


array_multisort($sortarray, SORT_ASC, $array);
}

调用函数,传递数组和二级数组字段的名称。 如:< / p >

sort_array_of_array($inventory, 'price');

在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

这正是usort所需要的。事实上,将<=>添加到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才能正常工作:

从比较函数返回< em >非整数< / em >值,例如float,将导致内部转换为回调返回值的整数。因此,像0.99和0.1这样的值都将被转换为0的整数值,这将把这两个值作为相等进行比较。

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

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




}
//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
)


)

从# EYZ0:

通过使用usort (http://php.net/usort),我们可以对数组进行升序和降序排序。只是我们需要创建一个函数,并将其作为参数传递给usort。按照下面的例子,使用大于表示升序,如果我们通过小于条件,那么它将按降序排序。 例子:< / p >

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

这个函数是可重用的:

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

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

您可以使用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);

如果你想在字符串上使用不区分大小写排序,你可以使用SORT_NATURAL|SORT_FLAG_CASE

array_multisort(array_column($inventory, 'key_name'), SORT_DESC, SORT_NATURAL|SORT_FLAG_CASE, $inventory);

完整动态函数 我跳到这里进行关联数组排序,并在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

这是我很久以前发现的一个方法,并进行了一些清理。这工作得很好,并且可以快速更改为接受对象。

/**
* 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;


}

要更改排序对象的方法,只需更改以下行:

< p > # EYZ0 来 # EYZ0 < / p >

要运行该方法,只需执行

# EYZ0

我像这样使用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);

试试这个:

$prices = array_column($inventory, 'price');
array_multisort($prices, SORT_DESC, $inventory);
print_r($inventory);

对于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");

如果需要对不同大小写的字符串数组进行排序,这将把排序数组的值更改为小写。

$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 7.4开始,你可以使用arrow函数:

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

代码(# EYZ0):

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

这个函数在所有主要版本的PHP上都可以100%运行,并且使用PHP5PHP7PHP8进行了测试。

    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();