我有以下数组:
$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
答案 0 :(得分:2)
您可以使用 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
答案 1 :(得分:1)
我建议尽可能少进行评估和尽可能少的函数调用。
我的代码段中故意使用了两个宇宙飞船操作符——这意味着 in_array()
调用仅在必要时执行。 spaceship operator 将处理排序规则数组,但这会降低效率,因为每次迭代都会调用所有 in_array()
函数。请勿使用此 demo。
代码:(Demo)
uksort(
$array,
fn($a, $b) =>
$array[$b] <=> $array[$a] // sort values DESC
?: in_array($b, $allowlist) <=> in_array($a, $allowlist) // sort keys with priority given to whitelisted keys
);
var_export($array);
这按值降序排序,然后通过检查 in_array()
是否降序来打破平局。对布尔结果进行排序时,降序将真置于假之前。
如果您正在处理大型阵列卷,那么我会敦促您避免使用 in_array()
。而是翻转您的查找数组并在您的自定义函数中使用 isset()
。
自定义函数的可见级联规则语法使其易于阅读和扩展。如果您想在两个或两个键都没有列入白名单时添加另一个决胜局,那么只需添加带有新规则的另一行:
?: $a <=> $b // sort by key ascending (alphabetically)