我有以下数组:
$array = [
'z' => 2,
'd' => 1,
'a' => 2,
];
现在我想按值(整数)排序,然后根据键是否在该白名单中进行排序:
$allowlist = ['a', 'd'];
所以我做了以下事情:
arsort($array);
uksort($array, function($a, $b) {
return in_array($a, $allowlist) ? -1 : 1;
});
但这会返回:
[d]: 1
[a]: 2
[z]: 2
我真正想要的是首先对值进行排序,然后如果存在平局断路器,则根据其是否在该允许列表中对键进行排序,这应该导致以下结果:
[a]: 2
[z]: 2
[d]: 1
您可以使用
uksort
为您提供键,并且您可以将 $array
传递到排序函数中以访问该值。
$array = [
'a' => 2,
'z' => 2,
'd' => 1
];
$allowlist = ['a', 'd'];
uksort(
$array,
static function($a, $b) use ($array, $allowlist) {
if($array[$a] === $array[$b]) {
return in_array($a, $allowlist) ? -1 : 1;
}
return $array[$b] <=> $array[$a];
}
);
这受到了这个答案的启发:https://stackoverflow.com/a/65315474/231316
我建议尽可能少地进行评估和函数调用。
这个原则使得
array_multisort()
成为这项任务的首选。 usort()
会比 array_map()
(具有线性时间复杂度)进行更多的迭代调用,这会拖累性能。
翻转白名单数组将允许其用作查找数组。由于按升序排序时
false
位于 true
之前,因此请检查查找中是否未找到该键。
$array
和参数 2:SORT_DESC
)代码:(演示)
$array = [
'z' => 2,
'd' => 1,
'a' => 2,
];
$allowlist = array_flip(['a', 'd']);
array_multisort(
$array,
SORT_DESC,
array_map(fn($k) => !isset($allowlist[$k]), array_keys($array)),
$array
);
var_export($array);
输出:
array (
'a' => 2,
'z' => 2,
'd' => 1,
)
该键使用按键上的
array_flip
功能。这给 uksort
一个可以比较的值:
$array = [
'a' => 2,
'z' => 2,
'd' => 1,
'e' => 1,
];
$allowlist = array_flip(['a', 'e', 'd']);
uksort(
$array,
static function($a, $b) use ($array, $allowlist) {
if ($array[$a] === $array[$b]) {
if (!key_exists($a,$allowlist) || !key_exists($b,$allowlist)) {
return 0;
}
return $allowlist[$a] <=> $allowlist[$b];
}
return $array[$b] <=> $array[$a];
}
);
echo '<pre>'.print_r($array,1).'</pre>';
结果:
Array
(
[a] => 2
[z] => 2
[e] => 1
[d] => 1
)