按值 DESC 对平面关联数组进行排序,然后按白名单键进行排序

问题描述 投票: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 arrays sorting associative-array 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
投票

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

这个原则使得

array_multisort()
成为这项任务的首选。
usort()
会比
array_map()
(具有线性时间复杂度)进行更多的迭代调用,这会拖累性能。

翻转白名单数组将允许其用作查找数组。由于按升序排序时

false
位于
true
之前,因此请检查查找中是否未找到该键。

  • 按值降序排序(参数 1:
    $array
    和参数 2:
    SORT_DESC
  • 按白名单数组中是否存在排序(param3)
  • 最终的参数会受到之前发生的各种影响。

代码:(演示

$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,
)

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.