【问题标题】:How to convert a flat array into a tree array based on dot notation and "type" attribute?如何基于点符号和“类型”属性将平面数组转换为树数组?
【发布时间】:2021-12-09 20:56:58
【问题描述】:

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

$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”,因此我使用“type”属性来区分它们。

我期待什么结果:

/*
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"
        ]
    ]
];

使用How to build a tree from a concatenated string in PHP? 中描述的方法我无法达到我想要的结果。 我现在能做什么?

【问题讨论】:

  • 您能分享您使用演示链接尝试过的内容吗?对数组进行排序让父母先于孩子是一个好的开始。
  • 请edit问题包含您当前尝试过的代码,以及它给出的输出或错误消息。
  • 在你的例子中。假设“Mango”变成了“category_label”:如何确定“Orange”的去向?

标签: php arrays multidimensional-array


【解决方案1】:

看看这个逻辑是否有帮助,我会在 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);
                    }
                }
            }
        }
    }
}

【讨论】:

    【解决方案2】:

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

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

    事实证明,您的层次结构编号不是唯一的(例如“1.1”)。如果希望父节点可以具有与“item”类型的兄弟节点相同的编号,但 same 类型的两个节点将永远不会具有相同的层次结构,则通过组合键节点类型和层次结构:

    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;
    }
    

    【讨论】:

    • 我印象深刻。但是它丢失了Citrusescategory_label1.1 编辑:我猜它被Mango1.1覆盖了
    • 我明白了,所以hierarchy 不是唯一的引用?应该如何解读?它是否总是只由带点的数字 1 组成,而不是任何其他数字?
    • 据我所知,他可以拥有很多。所以Fruits 是层次结构1,我想也可能有Buildings 和层次结构1。儿童也一样。
    • 提问者应该真正回答这个问题。
    • 如果你在$parent 中使用hierarchy AND title 就可以了
    猜你喜欢
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2012-09-26
    • 1970-01-01
    • 2021-08-11
    相关资源
    最近更新 更多