如何按字母顺序排序数组并保留树形结构?

3
我有两个长度/深度未知的数组,看起来是这样的:

[1] => Hand Tools
[2] => Power Tools
[4] =>  ╚═►Outdoor Tools
[6] =>    ╚═►dvjdg
[5] =>  ╚═►Indoor Tools
[7] =>    ╚═►blaha
[8] =>    ╚═►blahb
[3] => Garden Tools

并且。
[1] => 0
[2] => 0
[4] => 1
[6] => 2
[5] => 1
[7] => 2
[8] => 2
[3] => 0

两个数组都使用类别 id作为数组索引,第二个数组包含每个类别的深度。第一个数组用于生成HTML <select>输入,但现在我需要对该数组进行字母排序,同时保持正确的类别层级关系。所以我需要获得以下输出数组。

[3] => Garden Tools
[1] => Hand Tools
[2] => Power Tools
[5] =>  ╚═►Indoor Tools
[7] =>    ╚═►blaha
[8] =>    ╚═►blahb
[4] =>  ╚═►Outdoor Tools
[6] =>    ╚═►dvjdg

我该如何实现这个目标?

1
如果您能够从该列表中创建一个RecursiveIterator,那么您就可以对其进行排序:https://dev59.com/VHA85IYBdhLWcg3wHv3B#2932200 - hakre
3
我会建议你查阅array_multisort函数 - http://php.net/manual/zh/function.array-multisort.php - Austin Brunkhorst
两个数组都有已知的深度:1。 - hakre
你是如何将子元素与父元素关联起来的?仅仅通过深度是不够的吧?是通过父元素的ID来关联吗?如果能看到原始数组的print_r输出就好了。 - Baba
你可以在下面找到答案,递归迭代器在这里并不是必要的,它只是展示了一种为每个条目创建排序键的简单方法。 - hakre
1个回答

2

考虑到$list是您的数组,您无法轻松地对其进行排序,因为每个“子”元素都不携带其父元素的信息(文本)。因此,首先要做的是添加该信息:

  1. 获取级别。
  2. 为该级别设置当前值。
  3. 删除较高级别。
  4. 使用在文本中未使用的字符将所有级别合并在一起。

这样就得到了排序键。对于所有列表条目都执行此操作,就可以得到所有排序键:

$sortkeys = [];
$levels   = [];
foreach ($list as $index => $entry) {
    $level            = strspn($entry, ' ');
    $levels[$level]   = $entry;
    $sortkey          = implode('|', array_slice($levels, 0, $level + 1));
    $sortkeys[$index] = $sortkey;
}

这个例子简化了获取级别信息的过程。我每个级别计算了一个空格。你可能有不同的方式并使用不同于strspn的函数来实现。很可能你会用第二个数组来实现。我太懒了,所以用了这个函数。你的代码可能是这样的:

$level = $category_levels[$index];

现在,您可以根据$sortkeys数组对$list数组进行排序。这可以使用PHP的array_multisort函数完成。由于该函数会重新编号数字键,因此我们也要对键进行排序,然后在排序后组合以保留它们:
$keys = array_keys($list);
array_multisort($sortkeys, SORT_ASC, $list, $keys);

print_r(array_combine($keys, $list));

这将给你:

Array
(
    [3] => Garden Tools
    [1] => Hand Tools
    [2] => Power Tools
    [5] =>  ╚═►Indoor Tools
    [7] =>   ╚═►blaha
    [8] =>   ╚═►blahb
    [4] =>  ╚═►Outdoor Tools
    [6] =>   ╚═►dvjdg
)

查看完整的运行示例:演示


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