我有一个多维数组,我想根据距离值进行排序,其中应将错误值添加到其数组之前位置的末尾。
$array = array(
array('name' => 'Array 1', 'distance' => 3.4),
array('name' => 'Array 2', 'distance' => 2.4),
array('name' => 'Array 3', 'distance' => false),
array('name' => 'Array 4', 'distance' => 5.4),
array('name' => 'Array 5', 'distance' => false),
array('name' => 'Array 6', 'distance' => 1),
array('name' => 'Array 7', 'distance' => false),
array('name' => 'Array 8', 'distance' => false),
array('name' => 'Array 9', 'distance' => 3.6),
);
我想将其排序为:
Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 3
Array 5
Array 7
Array 8
我只能做到这一点:
Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 8
Array 5
Array 3
Array 7
我的尝试:
usort($array, function($a, $b){
if(!$b['distance'])
return -1;
elseif(!$a['distance'])
return 1;
return $a['distance'] - $b['distance'];
});
编辑:添加我的解决方案作为答案
// Filter items with NULL in distance
$withoutDistance = array_filter($array, function($item) { return !$item["distance"];});
// Take the rest
$withDistance = array_diff_assoc($array, $withoutDistance);
// Sort by distance
usort($withDistance, function($a, $b){
if ( $a['distance'] == $b['distance']) return 0;;
return $a['distance'] > $b['distance'] ? 1: -1; });
// Return NULL distance into array
$array = array_merge($withDistance, $withoutDistance);
这似乎完全符合您的要求,但请记住 array_reverse!。
usort($array, function($a, $b){
$isBFalse = is_bool($b['distance']) && $b['distance'] == false;
$isAFalse = is_bool($a['distance']) && $a['distance'] == false;
if($isBFalse && $isAFalse){
return 0;
}else if($isBFalse){
return 1;
}
else if($isAFalse){
return -1;
}
return $a['distance'] - $b['distance'];
});
$array = array_reverse($array);
分两步对数组进行排序的解决方案。第一步为每个元素计算一个排序键并将其存储在元素本身中。第二步使用第一步创建的排序键的简单字符串比较来进行实际排序。
代码:
$new = array_map(
function (array $item) {
return array(
'name' => $item['name'],
'distance' => $item['distance'],
'sort_key' => sprintf('%020.6f/%s',
$item['distance'] === false ? 999999 : $item['distance'],
$item['name']),
);
},
$array
);
usort(
$new,
function (array $a, array $b) {
return strcmp($a['sort_key'], $b['sort_key']);
}
);
排序后的数组位于变量
$new
中,原始数组$array
不受影响。
第一步生成一个新数组。数组中的每个条目都包含来自
$array
的原始条目以及名为 sort_key
的额外属性。
sort_key
的值是一个用于排序的字符串。排序标准是:
distance
的值并将false
放在最后;这意味着 false
大于任何非 false
值;name
的值;为了将
false
排序为大于任何非 false
distance
,请将 false
替换为一个大数字。上面的代码使用了999999
。调整此值以确保它比任何值都大distance
。
因为字符串是使用字典顺序排序的,所以
distance
的值(将false
替换为999999
)被格式化为固定长度字符串(20个字符,其中6个是小数),左填充与 0
。
名称附加到该字符串后;它已经是字符串,不需要任何其他处理。
sprintf('%020.6f/%s',
$item['distance'] === false ? 999999 : $item['distance'],
$item['name']),
);
对于
Array 1
,上面的 sprintf()
生成:
0000000000003.400000/Array 1
$withDistance = array();
$withoutDistance = array_filter($array, function($array) use (&$withDistance) {
if($array['distance'] !== false) {
$withDistance[] = $array;
return false;
}
return true;
});
usort($withDistance, function($a, $b){
if ($a['distance'] == $b['distance']) return 1;
return $a['distance'] > $b['distance'] ? 1: -1;
});
$array = array_merge($withDistance, $withoutDistance);
用宇宙飞船运算符和两条规则排序:
distance
是 false
,则 distance
排序。代码:(演示)
usort(
$array,
fn($a, $b) => [$a['distance'] === false, $a['distance']]
<=>
[$b['distance'] === false, $b['distance']]
);
var_export($array);