1,代码
/**
* 对二维数组依次按照排序规则数组指定的字段和顺序进行排序,在有相同的情况下按下一个字段和顺序进行排序
* @param array $arr 待排序的数组
* @param array $fieldSortMap:排序规则数组, 一维关联数组,每个元素的键为排序字段名称,值为排序方向:SORT_ASC升序或SORT_DESC降序
* @return array
*/
function multiSortByFields(array $arr, array $fieldSortMap) {
$count = count($arr);
if ($count <= 1 || empty($fieldSortMap)) {
return $arr;
}
$params = [];
//将排序字段所拥有的值分别放入数组中,以备排序
foreach ($fieldSortMap as $field => $sort) {
//field值数组,必须每个元素中都要有
$fieldValues = array_column($arr, $field);
if (count($fieldValues) != $count) {
return $arr;
}
//准备参数:依次分别是排序field的值数组和对应的排序方向(升序,降序)
$params[] = $fieldValues;
$params[] = $sort == SORT_ASC ? SORT_ASC : SORT_DESC;
// $params[] = SORT_NUMERIC;
}
//将原数组放入
$params[] = &$arr;
//排序
array_multisort(...$params);
return $arr;
}
核心思想是用 array_multisort() 方法,通过对字段的排序,最终影响数组的排序。
2,测试
$a = [
[
'a' => 1,
'b' => 111
],
[
'a' => 0,
'b' => 111
],
[
'a' => 3,
'b' => 333
],
[
'a' => 4,
'b' => 333
],
];
//先按b字段的值倒序排序,如b字段的值相同,则按a字段的值升序排序
$fieldSortMap = [
'b' => SORT_DESC,
'a' => SORT_ASC
];
$res = multiSortByFields($a, $fieldSortMap);
var_dump($res);
结果
array(4) {
[0]=>
array(2) {
["a"]=>
int(3)
["b"]=>
int(333)
}
[1]=>
array(2) {
["a"]=>
int(4)
["b"]=>
int(333)
}
[2]=>
array(2) {
["a"]=>
int(0)
["b"]=>
int(111)
}
[3]=>
array(2) {
["a"]=>
int(1)
["b"]=>
int(111)
}
}
3,思考
这里只是二维数组,看能否用 array_walk_recursive() 递归地实现 对多维数组的多字段多方向排序。