通过键将平面数组分组为多维数组,如果我们不知道那里有多少个层次。的PHP

时间:2018-12-17 16:28:51

标签: php arrays algorithm sorting multidimensional-array

我有这个数组:

$arr = [
["id"=>20,
    "name"=>"a",
    "parent"=>28,
],
["id"=>21,
    "name"=>"a-child",
    "parent"=>20,
],
["id"=>27,
    "name"=>"a-child-b",
    "parent"=>20,
],
["id"=>28,
   "name"=>"A parent",
   "parent"=>0,
],
["id"=>12,
    "name"=>"no parent",
    "parent"=>0,
]];

我要基于parent键对其进行分组,其中parent = id && parent > 0id是该元素的父元素,并且如果父键更大,则该元素具有父元素大于零。

在上面的数组id=12中没有父级,id=20有子级21, 27,它是id=28的子级。

我做了什么:

    public function sort($arr){

    $result = [];

    // Get child
    foreach($arr as $key => $row) {
        if($row['parent'] > 0) {
            $result[$row->parent][] = ['id' => $row['id'], 'name' => $row['name']];
            unset($arr[$key]);
        }
    }

    // Get parent and append child
    foreach($arr as $key => $row) {
        $result[$row['id']] = ['name' => $row['name'],
                              'child' => $result[$row['id']]];

    }
    return $result;
}

问题是,这仅适用于parent => child array()之类的1个孩子。

我想做的是一种获取参数(在数组上方)的方法,我不知道要进行多少层嵌套并按parent键数组分组返回:

$arr = [
["id"=>28,
 "name"=>"A parent",
 "parent"=>0,
    'child' => [
        ["id"=>20,
             "name"=>"a",
             "parent"=>28,
             'child' => [
                 ["id"=>21,
                  "name"=>"a-child",
                  "parent"=>20,
                 ],
                 ["id"=>27,
                  "name"=>"a-child-b",
                  "parent"=>20,
                 ]
             ]
        ]
    ]
],
["id"=>12,
 "name"=>"no parent",
 "parent"=>0,
]];

2 个答案:

答案 0 :(得分:2)

这是一种分两步的方法,首先构建将父对象映射到其子对象数组的关联数组,然后通过索引到父子关联数组来递归填充children键。

请注意,我假设parent => 0是根,但这也是可以调整的。我还使用了密钥children,我觉得它更具有语义,但是可以随时还原为child

function insert(&$curr, $parents) {
    if (array_key_exists($curr['id'], $parents)) {
        $curr['children'] = $parents[$curr['id']];
    }

    if (array_key_exists('children', $curr)) {
        foreach ($curr['children'] as &$child) {
            insert($child, $parents);
        }
    }
}

function treeify($arr) {
    foreach ($arr as $e) {
        $parents[$e['parent']][] = $e;
    }

    foreach ($parents[0] as &$root) {
        insert($root, $parents);
    }

    return $parents[0];
}

输出:

Array
(
    [0] => Array
        (
            [id] => 28
            [name] => A parent
            [parent] => 0
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 20
                            [name] => a
                            [parent] => 28
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 21
                                            [name] => a-child
                                            [parent] => 20
                                        )

                                    [1] => Array
                                        (
                                            [id] => 27
                                            [name] => a-child-b
                                            [parent] => 20
                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [id] => 12
            [name] => no parent
            [parent] => 0
        )

)

Try it!

答案 1 :(得分:2)

<?php

define('ROOT_PARENT',0);

function getHierarchy($records){
    $hierarchy = [];

    /*
        let's assume everybody is going to be a parent
    */

    foreach($records as $each_record){
        $each_record['child'] = [];
        $hierarchy[$each_record['id']] = $each_record;
    }

    /*
       Now add child to parent's key in $hierarchy in the 'child' key. 
       The & is important since there may be future childs for current child. So pass by reference is needed
    */
    foreach($records as $each_record){
        $hierarchy[$each_record['parent']]['child'][] = &$hierarchy[$each_record['id']];
    }

    /* 
        here I unset every key which wasn't at root level,i.e is 0(top) level
    */
    foreach($hierarchy as $parent => $its_data){
        if($parent != ROOT_PARENT){
            unset($hierarchy[$parent]);
        }
    }

    return isset($hierarchy[ROOT_PARENT],$hierarchy[ROOT_PARENT]['child']) ? $hierarchy[ROOT_PARENT]['child'] : [];
}

$records = [
            [
                "id" => 20,
                "name" => "a",
                "parent" => 28,
            ],
            [
                "id" => 21,
                "name" => "a-child",
                "parent" => 20,
            ],
            [
                "id" => 27,
                "name" => "a-child-b",
                "parent" => 20,
            ],
            [
                "id" => 28,
               "name" => "A parent",
               "parent" => 0,
            ],
            [
                "id" => 12,
                "name" => "no parent",
                "parent" => 0,
            ]
    ];


echo "<pre>";
print_r(getHierarchy($records));

输出:

Array
(
    [0] => Array
        (
            [id] => 28
            [name] => A parent
            [parent] => 0
            [child] => Array
                (
                    [0] => Array
                        (
                            [id] => 20
                            [name] => a
                            [parent] => 28
                            [child] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 21
                                            [name] => a-child
                                            [parent] => 20
                                            [child] => Array
                                                (
                                                )

                                        )

                                    [1] => Array
                                        (
                                            [id] => 27
                                            [name] => a-child-b
                                            [parent] => 20
                                            [child] => Array
                                                (
                                                )

                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [id] => 12
            [name] => no parent
            [parent] => 0
            [child] => Array
                (
                )

        )

)

首先,我们认为每个人都可以成为父母。然后,在它的父级child键中,我们继续添加它的子级。我们通过参考传递key,因为将来可能会有孩子。最后,unset()来自层次结构的不是根父级的每个人。最后,您将拥有最终的层次结构。