按父/子 ID 重组数组。递归?

Posted

技术标签:

【中文标题】按父/子 ID 重组数组。递归?【英文标题】:Restructure array by parent/child IDs. Recursion? 【发布时间】:2011-04-21 16:36:08 【问题描述】:

我有一系列位置。这些位置中的每一个都可以有子位置。每个子位置也可以有子位置,依此类推:

$locations = array(
    array("id" => 1,  "parent_id" => 0, "name" => "England"),
    array("id" => 2,  "parent_id" => 0, "name" => "Scotland"),
    array("id" => 3,  "parent_id" => 0, "name" => "Ireland"),
    array("id" => 4,  "parent_id" => 0, "name" => "Wales"),
    array("id" => 5,  "parent_id" => 1, "name" => "East England"),
    array("id" => 6,  "parent_id" => 1, "name" => "London"),
    array("id" => 7,  "parent_id" => 6, "name" => "West London"),
    array("id" => 8,  "parent_id" => 6, "name" => "East London"),
    array("id" => 9,  "parent_id" => 1, "name" => "East Midlands"),
    array("id" => 10, "parent_id" => 9, "name" => "Derbyshire")
);

我想重新构造这个数组,使子数组成为父数组。像这样的东西(未经测试):

$locations =    array("id" => 1, "parent_id" => 0, "name" => "England", "children" => array(
                    array("id" => 5,  "parent_id" => 1, "name" => "East England"),
                    array("id" => 6,  "parent_id" => 1, "name" => "London", "children" => array(
                            array("id" => 7,  "parent_id" => 6, "name" => "West London"),
                            array("id" => 8,  "parent_id" => 6, "name" => "East London")))));

这样我就可以像这样使用缩进打印出来:

LOCATIONS

England
- East England
- London
-- West London
-- East London
- East Midlands
-- Derbyshire
Scotland
Ireland
Wales

我已经尝试了几种方法,比如按父 ID 对它们进行分组,但我就是想不出这样做的逻辑,并且可能有更好的方法(也许是递归?)。

非常感谢。

【问题讨论】:

您能添加一些您尝试过的代码示例吗?顺便说一句,递归可能是通过引用将结果传递给函数的最佳方法。 【参考方案1】:

嗨,也许这会对你有所帮助,我只是为了快速将包含 parent_id 的 mysql 结果转换为可用的数据层次结构而编写它。您的输入数组也应该可以工作。这只是带有两个基本循环的几行代码。不需要递归。包括一些 cmets:

<?php

$max = count($inputArray);
$tree = array();
$flat = array();
// Create a flat hierarchy array of all entries by their id
for ($i = 0; $i < $max; $i++) 
        $n = $inputArray[$i];
        $id = $n['page_id'];
        $flat[$id] = $n;

// Then check all those entries by reference
foreach ($flat as $key => &$child) 
        // Add a children array if not already existing
        if (!isset($child['children']))
                $child['children'] = array();

        $id = $child['page_id'];
        $pid = $child['parent_id'];

        // If childs parent id is larger then zero
        if ($pid > 0) 
                // Append it by reference, which means it will reference
                // the same object across different carriers
                $flat[$pid]['children'][] = &$child;
         else 
                // Otherwise it is zero level, which initiates the tree
                $tree[$id] = &$child;
        


$tree = array_values($tree); // Indices fixed, there we go, use $tree further
?>

因此请注意 by '& reference' 字符。他们完成了所有工作,允许通过指向相同的对象从平面数组构建树。

【讨论】:

【参考方案2】:

看到这个excellent anwser from Bill Kalwin

还有他的presentation on "Models for hierarchical data (PHP and SQL)"

另外,您可能对storing directly data as a "nested set" structure in your DB 感兴趣。

【讨论】:

以上是关于按父/子 ID 重组数组。递归?的主要内容,如果未能解决你的问题,请参考以下文章

类别的递归数组和子类别 PHP

递归函数和多维数组

PHP - 当给定子键名时,递归地将每个数组元素的键设置为子元素的值

平面数组重组为树数组

js 组对象中相同属性值求和,(数值相加,数组重组)

递归PHP函数写入外部数组