如何根据点表示法和"type"属性将平面数组转换为树形数组?



我想在下面转换一个平面数组:

$array = [
[
"hierarchy" => "1",
"title" => "Fruits",
"type" => "category_label"
],
[
"hierarchy" => "1.1",
"title" => "Citruses",
"type" => "category_label"
],
[
"hierarchy" => "1.1.1",
"title" => "Orange",
"type" => "item"
],
[
"hierarchy" => "1.1",
"title" => "Mango",
"type" => "item"
],
[
"hierarchy" => "1.2",
"title" => "Grape",
"type" => "item"
]
];
从上面可以看到,它有两个分层的点标记字符串"1.1",因此我使用"类型"属性来区分它们。

我期望的结果:

/*
1. Fruits
-  1.1. Citruses
--- 1.1.1. Orange
-- 1.1. Mango
-- 1.2. Grape
*/
//Desired result
[
"hierarchy" => "1",
"title" => "Fruits",
"type" => "category_label",
"children" => [
[
"hierarchy" => "1.1",
"title" => "Citruses",
"type" => "category_label"
"children" => [
[
"hierarchy" => "1.1.1",
"title" => "Orange",
"type" => "item"
]
]
],
[
"hierarchy" => "1.1",
"title" => "Mango",
"type" => "item"
],
[
"hierarchy" => "1.2",
"title" => "Grape",
"type" => "item"
]
]
];

使用方法描述在如何建立一个树从一个连接的字符串在PHP?我不能达到我想要的结果。我现在能做什么?

首先可以在新的关联数组中按层次结构键入所有项。然后再次迭代这些项,并删除hierarchy的最后一部分以获得父项的键,在新的关联数组中定位它,并将其添加到它的子数组中。如果它没有父元素,则将其添加到结果数组中。

由于您的hierarchy分隔符是一个点,您可以使用pathinfo函数来删除最后一个扩展名"来自:

原来你的层次编号不是唯一的(例如"1.1")。如果希望父节点可以与"item"类型的兄弟节点具有相同的编号,但相同类型的两个节点永远不会具有相同的层次结构,则通过type和层次结构的组合对节点进行键设置:

foreach ($array as $item) $keyed[$item["type"] . $item["hierarchy"]] = $item;
foreach ($keyed as &$item) {
$parent = pathinfo($item["hierarchy"], PATHINFO_FILENAME);
if ($parent == $item["hierarchy"]) $result[] =& $item;
else $keyed["category_label$parent"]["children"][] =& $item;
}

运行此命令后,$result将具有所需的结构。

然而,我建议使层次结构代码唯一,这样它们就不会在不同类型之间发生冲突。然后可以将上面的代码更改为:
foreach ($array as $item) $keyed[$item["hierarchy"]] = $item;
foreach ($keyed as &$item) {
$parent = pathinfo($item["hierarchy"], PATHINFO_FILENAME);
if ($parent == $item["hierarchy"]) $result[] =& $item;
else $keyed[$parent]["children"][] =& $item;
}

看看这个逻辑是否有帮助,我会尝试在1天内编辑答案并解释。

$tree_array = [];
foreach($array as $key => $value){
if(count(explode('.',$value['hierarchy']) == 1){
array_push($array_tree, $value)
}
}
foreach($array as $value){
if(count(explode('.',$value['hierarchy'])) == 2){
if($value['type'] == 'category_label'){
foreach($array_tree as $key =>  $tree){
if($tree['hierarchy'] == explode('.',$value['hierarchy'])[0]){
array_push($array_tree['children'],$value);
}
}
} else {
foreach($array_tree as $key =>  $tree){
if($tree['hierarchy'] == explode('.',$value['hierarchy'])[0]){
array_push($array_tree[$key],$value);
}
}
}
}
}
foreach($array as $value){
if(count(explode('.',$value['hierarchy'])) == 3){
if($value['type'] == 'item'){
foreach($array_tree as $key => $tree){
foreach($tree as $item){
if($item['hierarchy'] == explode('.',$value['hierarchy'],2)[1]){
array_push($array_tree[$key]['children'],$value);
}
}
}
}
}
}