【问题标题】:How to build grouped tree array from flat array in php如何从 php 中的平面数组构建分组树数组
【发布时间】:2022-02-10 17:27:37
【问题描述】:

我正在尝试将数组重新格式化为树,主数组和子数组应按“名称”属性分组。

我的平面数组是这样的

$flat = [
    ['id' => 1, 'parent_id' => 0, 'name' => 'root1'],
    ['id' => 2, 'parent_id' => 0, 'name' => 'root1'],
    ['id' => 3, 'parent_id' => 1, 'name' => 'ch-1'],
    ['id' => 4, 'parent_id' => 1, 'name' => 'ch-1'],
    ['id' => 5, 'parent_id' => 3, 'name' => 'ch-1-1'],
    ['id' => 6, 'parent_id' => 3, 'name' => 'ch-1-1'],
    ['id' => 7, 'parent_id' => 0, 'name' => 'root2'],
    ['id' => 8, 'parent_id' => 0, 'name' => 'root2'],
    ['id' => 9, 'parent_id' => 7, 'name' => 'ch3-1'],
    ['id' => 10, 'parent_id' => 7, 'name' => 'ch3-1']
];

我可以通过

构建树结构
$tree = buildTree($flat, 'parent_id', 'id');

function buildTree(array $flatList)
{
    $grouped = [];
    foreach ($flatList as $node) {
        $grouped[$node['parent_id']][] = $node;
    }

    $fnBuilder = function ($siblings) use (&$fnBuilder, $grouped) {
        foreach ($siblings as $k => $sibling) {
            $id = $sibling['id'];
            if (isset($grouped[$id])) {
                $sibling['children'] = $fnBuilder($grouped[$id]);
            }
            $siblings[$k] = $sibling;
        }
        return $siblings;
    };

    return $fnBuilder($grouped[0]);
}

这很好用。

但我想要的是构建嵌套数组应该按它的“名称”属性分组。

所以最终的输出应该是这样的

[
  "root1": [{
      "id": 1,
      "parent_id": 0,
      "name": "root1",
      "children": [
        "ch-1": [{
            "id": 3,
            "parent_id": 1,
            "name": "ch-1",
            "children": [
              "ch-1-1": [{
                  "id": 5,
                  "parent_id": 3,
                  "name": "ch-1-1"
                },
                {
                  "id": 6,
                  "parent_id": 3,
                  "name": "ch-1-1"
                }
              ]
            ]
          },
          {
            "id": 4,
            "parent_id": 1,
            "name": "ch-1"
          }
        ]
      ]
    },
    {
      "id": 2,
      "parent_id": 0,
      "name": "root1"
    }
  ],
  "root2": [{
      "id": 7,
      "parent_id": 0,
      "name": "root2",
      "children": [
        "ch3-1": [{
            "id": 9,
            "parent_id": 7,
            "name": "ch3-1"
          },
          {
            "id": 10,
            "parent_id": 7,
            "name": "ch3-2"
          }
        ]
      ]
    },
    {
      "id": 8,
      "parent_id": 0,
      "name": "root2"
    }
  ]
]

我几乎被困在这里几天了。请帮我解决这个问题。 谢谢。

【问题讨论】:

  • 有没有可能同名不同的parent_id?
  • No.. 不能有同名但不同的parent_id。
  • 这能回答你的问题吗? Build a tree from a flat array in PHP
  • 我可以构建树形数组,但问题是格式化的数组应该被分组。

标签: php arrays multidimensional-array


【解决方案1】:
function buildTree(array $flat)
    {
        $grouped = [];
        foreach ($flat as $node) {
            $grouped[$node['parent_id']][] = $node;
        }

        $fnBuilder = function ($siblings) use (&$fnBuilder, $grouped) {
            foreach ($siblings as $k => $sibling) {
                $id = $sibling['id'];
                if (isset($grouped[$id])) {
                    $sibling['children'] = $fnBuilder($grouped[$id]);
                }
                $siblings[$k] = $sibling;
            }
            return $siblings;
        };
        return $fnBuilder($grouped[0]);
    }


$tree = buildTree($flat);

将树结构数组传递给groupedTree();

$groupd = groupedTree($tree);

echo json_encode($groupd, JSON_PRETTY_PRINT);


function groupedTree($tree)
    {
        $groupedByFuncTableName = array_reduce($tree, function (array $accumulator, array $element) {
            if (isset($element['children'])) {
                $element['children'] = groupedTree($element['children']);
            }
            $accumulator[$element['name']][] = $element;

            return $accumulator;
        }, []);
        return $groupedByFuncTableName;
    }

【讨论】:

    【解决方案2】:

    unset() 中使用类似这样的函数

    function buildTree(array &$flat, $parentId = 0) {
        $branch = array();
    
        foreach ($flat as $element) {
            if ($element['parent_id'] == $parentId) {
                $children = buildTree($flat, $element['id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[$element['id']] = $element;
            unset($flat[$element['id']]);
            }
        }
        return $branch;
    }
    

    在 buildTree 之后,我们需要按名称分组这是我的代码:-

    $result = array();
    foreach ($buildTree as $element) {
        $result[$element['name']][] = $element;
    }
    

    希望对您有所帮助。查看here的详细信息

    谢谢

    【讨论】:

    • 格式化数组应按“名称”属性分组。但这不能正确分组数组
    • 好的,@IsuruRodrigo!我的错,让我更新这个答案。
    • 嘿,@IsuruRodrigo,您能否从这里检查此代码 onecompiler.com/php/3xsv4ucvt 另外,我更新了我的答案。
    • 您的答案几乎正确,但这不会对嵌套对象进行分组。它只对父对象进行分组。似乎需要使用递归函数来做到这一点。但我不知道
    • 好的,我希望我能帮助你得到正确的结果。 ?
    【解决方案3】:
    function buildTree2(array $flatList)
    {
        $groupedchildren = [];
        $groupedparents = [];
        foreach ($flatList as $node) {
            if($node['parent_id'] == 0){
                $groupedparents[$node['parent_id']][] = $node;
            }else{
                $groupedchildren[$node['parent_id']][] = $node;
            }
        }
        
        $namegroupedparents = [];
        foreach ($groupedparents as $parent_group) {
            foreach ($parent_group as $node) {
                $namegroupedparents[$node['name']][] = $node;
            }
        }
        
        $namegroupedchildren = [];
        foreach ($groupedchildren as $children_group) {
            foreach ($children_group as $node) {
                $namegroupedchildren[$node['name']][] = $node;
            }
        }
        
        $fnBuilder = function (&$namegroupedparents) use (&$fnBuilder, $namegroupedchildren) {
            foreach($namegroupedparents as &$named){
                foreach($named as &$parentgroup){
                    $id = $parentgroup['id'];
                    foreach($namegroupedchildren as $thename => $namedall){
                        foreach($namedall as $childgroup){
                            if($childgroup['parent_id'] == $id){
                                if(isset($parentgroup['children'])){
                                    if(!in_array($childgroup, $parentgroup['children'][$thename])){
                                        $parentgroup['children'][$thename][] = $childgroup;
                                    }
                                }else{
                                    $parentgroup['children'][$thename][] = $childgroup;
                                }
                                $fnBuilder($parentgroup['children']);
                            }
                        }
                    }
                }
            } 
            return;
        };
    
        $fnBuilder($namegroupedparents);
        
        return $namegroupedparents;
    }
    

    这适用于您当前的数组,但我不知道它是否适用于不同的输入。

    它按parent_id 分组,然后按name 分组,同时将0 父母与其他孩子放在不同的数组中。然后它通过递归构建children数组。

    【讨论】:

      猜你喜欢
      • 2016-09-25
      • 1970-01-01
      • 2019-10-12
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      相关资源
      最近更新 更多