按值对 PHP 数组排序,然后按自定义顺序键

问题描述 投票:0回答:3

我有以下数组:

$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
php sorting custom-sort
3个回答
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

此处演示:https://3v4l.org/toZIt


1
投票

我建议尽可能少地进行评估和函数调用。

我的代码片段中故意有两个宇宙飞船运算符——这意味着

in_array()
调用仅在必要时执行。宇宙飞船运算符将处理排序规则数组,但这会降低效率,因为每次迭代都会调用所有
in_array()
函数。不要使用这个演示

代码:(演示

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()
是否降序来打破平局。对布尔结果进行排序时,降序将 true 放在 false 之前。

如果您正在处理大型数组,那么我会敦促您避免

in_array()
。相反,翻转查找数组并在自定义函数中使用
isset()

自定义函数的可见级联规则语法使其易于阅读和扩展。如果您想在两个或两个键均未列入白名单时添加另一个决胜局,则只需使用新规则添加另一行即可:

?: $a <=> $b  // sort by key ascending (alphabetically)

0
投票

该键使用按键上的

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
)
© www.soinside.com 2019 - 2024. All rights reserved.