递归地对多维数组的键进行排序

21

我正在尝试对多维数组按其键进行递归排序,但使用usort()没有成功。

样例数据:

[
    'first_level' => [
        'dir_3' => [
            'subdir_1' => [
                'file_2.mp4' => (object) [
                    'name' => 'file_2.mp4',
                ],
                'file_1.mp4' => (object) [
                    'name' => 'file_1.mp4',
                ],
            ],
        ],
        'dir_1' => [
            'subdir_2' => [
                'file_6.mp4' => (object) [
                    'name' => 'file_6.mp4',
                ],
                'file_9.mp4' => (object) [
                    'name' => 'file_9.mp4',
                ],
                'file_7.mp4' => (object) [
                    'name' => 'file_7.mp4',
                ],
            ],
            'subdir_1' => [
                'file_8.mp4' => (object) [
                    'name' => 'file_8.mp4',
                ],
            ],
        ],
    ],
]

期望的结果:

[
    'first_level' => [
        'dir_1' => [
            'subdir_1' => [
                'file_8.mp4' => (object) [
                    'name' => 'file_8.mp4',
                ],
            ],
            'subdir_2' => [
                'file_6.mp4' => (object) [
                    'name' => 'file_6.mp4',
                ],
                'file_7.mp4' => (object) [
                    'name' => 'file_7.mp4',
                ],
                'file_9.mp4' => (object) [
                    'name' => 'file_9.mp4',
                ],
            ],
        ],
        'dir_3' => [
            'subdir_1' => [
                'file_1.mp4' => (object) [
                    'name' => 'file_1.mp4',
                ],
                'file_2.mp4' => (object) [
                    'name' => 'file_2.mp4',
                ],
            ],
        ],
    ],
]
4个回答

38

使用递归函数对当前层级和所有更深层次的子数组调用 ksort。

function recur_ksort(&$array) {
    foreach ($array as &$value) {
        if (is_array($value))
            recur_ksort($value);
     }
     ksort($array);
}

recur_ksort($array);
var_export($array);

演示:https://3v4l.org/Xede5


2
这个回答让我发现了自己代码中一个愚蠢的错误。:o 我自己也想出了一些非常相似的代码,但是我忘记在&$value之前加上&,所以我一直在纠结为什么只有我的第一层被排序了。谢谢你无意中帮助了我。;) - Byson

5

您需要使用递归与ksort演示

function recursive_ksort(&$array) {
    foreach ($array as &$v) {
        if (is_array($v)) {
            recursive_ksort($v);
        }
    }
    ksort($array);
}

recursive_ksort($array);
var_export($array);

4
function ksort_recursive(&$array)
{
    if (is_array($array)) {
        ksort($array);
        array_walk($array, 'ksort_recursive');
    }
}

在递归函数内部,不必使用return ksort() -- 这会从ksort()返回不需要的成功布尔值。
请注意,当给定非数组时,此函数不会抛出“Warning: ksort() expects parameter 1 to be array”错误 - 这符合我的要求,但可能不符合您的要求。示例:https://3v4l.org/bogAU

1

可以合理地假设您希望数据被“自然”排序--这意味着目录和文件名的数字部分应该按数字顺序而不是简单字符串排序。如果不进行自然排序,dir_10将被移动到dir_2之前,因为在比较两个字符串的第5个字符时,1小于2。

代码:(演示

function nat_ksort_r(&$data): void
{
    if (is_array($data)) {
        ksort($data, SORT_NATURAL);
        array_walk($data, __METHOD__);
    }
}

nat_ksort_r($array);
var_export($array);
  • 为了进行自然排序,请在ksort()调用中应用SORT_NATURAL标志。
  • 为了更简单地维护递归函数,请使用__METHOD__魔术常量来调用函数。如果您希望将自定义函数命名为其他名称,则可以少改变一个地方的nat_ksort_r()
  • 此递归函数不返回任何数据;它通过引用修改原始数组。
  • 最低级别包含对象,该数据不会被函数排序。

上述函数还可以使用经典循环而不是功能迭代器。(演示

function nat_ksort_r(&$data): void
{
    if (is_array($data)) {
        ksort($data, SORT_NATURAL);
        foreach ($data as &$item) {
            (__METHOD__)($item);
        }
    }
}

nat_ksort_r($array);
var_export($array);

你甚至可以完全匿名地编写代码。演示

$nat_ksort_r = function(&$data) use (&$nat_ksort_r) {
    if (is_array($data)) {
        ksort($data, SORT_NATURAL);
        foreach ($data as &$item) {
            $nat_ksort_r($item);
        }
    }
};
$nat_ksort_r($array);
var_export($array);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接