Php 使用子元素的值将多维数组重新排序为层次结构

Php 使用子元素的值将多维数组重新排序为层次结构,php,arrays,multidimensional-array,Php,Arrays,Multidimensional Array,我需要使用单个数组中的group\u parent\u id作为参考,将平面多维数组转换为层次结构 一个烦恼是,我只能处理用户有权访问的组的子集合,因此,尽管测试组本身是一个子组,但由于访问权限,它的父组实际上不在列表中。因此,从这个用户的角度来看,测试组将被视为根级别 不幸的是,这陷入了递归,这不是我的强项 输入: $arr = [ [ 'group_id' => 5, 'group_title' => 'Test group',

我需要使用单个数组中的
group\u parent\u id
作为参考,将平面多维数组转换为层次结构

一个烦恼是,我只能处理用户有权访问的组的子集合,因此,尽管
测试组本身是一个子组,但由于访问权限,它的父组实际上不在列表中。因此,从这个用户的角度来看,
测试组
将被视为根级别

不幸的是,这陷入了递归,这不是我的强项

输入:

$arr = [
    [
        'group_id' => 5,
        'group_title' => 'Test group',
        'group_parent_id' => 2
    ],
    [
        'group_id' => 6,
        'group_title' => 'Second-level test group',
        'group_parent_id' => 5
    ],
    [
        'group_id' => 7,
        'group_title' => 'Third-level test group',
        'group_parent_id' => 6
    ],
    [
        'group_id' => 8,
        'group_title' => 'Other test group',
        'group_parent_id' => 1
    ],
    [
        'group_id' => 9,
        'group_title' => 'Second-level other test group',
        'group_parent_id' => 8
    ]
];
$arr = [
    [
        'group_id' => 5,
        'group_title' => 'Test group',
        'group_parent_id' => 2,
        'subgroups' => [
            [
                'group_id' => 6,
                'group_title' => 'Second-level test group',
                'group_parent_id' => 5,
                'subgroups' => [
                    [
                        [
                            'group_id' => 7,
                            'group_title' => 'Third-level test group',
                            'group_parent_id' => 6
                        ]
                    ]
                ]
            ]
        ]
    ],
    [
        'group_id' => 8,
        'group_title' => 'Other test group',
        'group_parent_id' => 1,
        'subgroups' => [
            [
                'group_id' => 9,
                'group_title' => 'Second-level other test group',
                'group_parent_id' => 8
            ]
        ]
    ]
];
所需输出:

$arr = [
    [
        'group_id' => 5,
        'group_title' => 'Test group',
        'group_parent_id' => 2
    ],
    [
        'group_id' => 6,
        'group_title' => 'Second-level test group',
        'group_parent_id' => 5
    ],
    [
        'group_id' => 7,
        'group_title' => 'Third-level test group',
        'group_parent_id' => 6
    ],
    [
        'group_id' => 8,
        'group_title' => 'Other test group',
        'group_parent_id' => 1
    ],
    [
        'group_id' => 9,
        'group_title' => 'Second-level other test group',
        'group_parent_id' => 8
    ]
];
$arr = [
    [
        'group_id' => 5,
        'group_title' => 'Test group',
        'group_parent_id' => 2,
        'subgroups' => [
            [
                'group_id' => 6,
                'group_title' => 'Second-level test group',
                'group_parent_id' => 5,
                'subgroups' => [
                    [
                        [
                            'group_id' => 7,
                            'group_title' => 'Third-level test group',
                            'group_parent_id' => 6
                        ]
                    ]
                ]
            ]
        ]
    ],
    [
        'group_id' => 8,
        'group_title' => 'Other test group',
        'group_parent_id' => 1,
        'subgroups' => [
            [
                'group_id' => 9,
                'group_title' => 'Second-level other test group',
                'group_parent_id' => 8
            ]
        ]
    ]
];
我尝试了几种不同的方法,但未能达到上述要求:

function build_group_tree(array $groups, $group_ids = [])
{
    $output = [];

    foreach ($groups as $group) {
        if (in_array($group['group_parent_id'], $group_ids)) {
            $children = build_group_tree($groups, $group['group_id']);

            if ($children) {
                $group['subgroups'] = $children;
            }

            $output[] = $group;
        }
    }

    return $output;
}

build_group_tree($arr, array_column($arr, 'group_id));
这给了我一个部分结果,但不包括所有的组


感谢您的帮助。

一种方法是迭代数组,在输出数组中创建每个
组id
项的引用列表,然后通过引用添加子项:

$output = array();
$group_ids = array();
foreach ($arr as $el) {
    $parent_id = $el['group_parent_id'];
    if (!isset($group_ids[$parent_id])) {
        // must be a top-level element
        $output[] = $el;
        // save a pointer
        $group_ids[$el['group_id']] = &$output[array_key_last($output)];
    }
    else {
        // already exists, $group_ids[$parent_id] points to the entry
        $parent = &$group_ids[$parent_id];
        if (!isset($parent['subgroups'])) {
            // no subgroups array, create one
            $parent['subgroups'] = array();
        }
        // add this entry to the subgroups
        $parent['subgroups'][] = $el;
        // save a pointer
        $group_ids[$el['group_id']] = &$parent['subgroups'][array_key_last($parent['subgroups'])];
    }
}
print_r($output);
输出:

Array
(
    [0] => Array
        (
            [group_id] => 5
            [group_title] => Test group
            [group_parent_id] => 2
            [subgroups] => Array
                (
                    [0] => Array
                        (
                            [group_id] => 6
                            [group_title] => Second-level test group
                            [group_parent_id] => 5
                            [subgroups] => Array
                                (
                                    [0] => Array
                                        (
                                            [group_id] => 7
                                            [group_title] => Third-level test group
                                            [group_parent_id] => 6
                                        )
                                )
                        )
                )
        )
    [1] => Array
        (
            [group_id] => 8
            [group_title] => Other test group
            [group_parent_id] => 1
            [subgroups] => Array
                (
                    [0] => Array
                        (
                            [group_id] => 9
                            [group_title] => Second-level other test group
                            [group_parent_id] => 8
                        )
                )
        )
)

请注意,此代码使用的是仅在7.3版中引入到PHP的。如果您使用的是早期版本,请在其位置使用
count($array)-1