在PHP中从一个平面数组构建树形结构

55
我在互联网上找了一圈,仍然没有找到我要的内容。我有一个平面数组,每个元素都包含一个“id”和一个“parent_id”。每个元素只会有一个父级,但可能有多个子级。如果parent_id = 0,则视为根级项。我正在尝试将我的平面数组转换成树形结构。我发现的其他示例只是将元素复制到父级,但原始元素仍然存在。
编辑
起始数组的每个元素都从单独的XML文件中读取。如果没有父级,则parent_id的值为“0”。键实际上是字符串。
对之前的混淆表示抱歉。希望这样更清楚:
/编辑
我的起始数组:
结果数组(树形结构):
        function buildTree(array &$elements, $parentId = 0) {
        $branch = array();
foreach ($elements as $element) { if ($element['parent_id'] == $parentId) { $children = $this->buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[] = $element; } }
return $branch; }

这段代码用于构建一个树形结构,输入一个多维数组 $elements 和父级 ID $parentId。

首先,定义了一个名为 $branch 的空数组,用于保存构建好的树形结构。

然后,使用 foreach 循环遍历 $elements 数组中的每个元素。如果该元素的 parent_id 等于当前传入的 parentId,则说明这个元素是当前节点的子节点,需要将其加入到 $branch 数组中,并递归调用 buildTree 函数,查找该元素是否还有子节点。

最后,返回 $branch 数组,即为构建好的树形结构。


1
我有点困惑。你是在要求我们编写代码,将第一个数组的内容输出为第二个数组吗? - MetalFrog
是的...这里的问题是什么? - Wes Crow
简而言之,我猜是这样的。我看了很多其他的例子,包括stackoverflow上和其他博客/论坛上的例子。但是当我尝试它们时,它们并不起作用。 - DSkinner
如果您一开始就创建了该数组,为什么不通过搜索数组的parent_id自动将其排序为树形结构呢? - Daniel West
邻接模型相对于嵌套集模型具有许多优点(在更改位置时,嵌套集模型非常昂贵)。Bill的幻灯片展示了不同模型成本的便捷概述:http://www.slideshare.net/billkarwin/models-for-hierarchical-data。请注意,在PosgresSQL、Oracle、DB2和MSSQL中,邻接列表比在MySQL中更可行(期待它们实现它)。 - Wrikken
显示剩余3条评论
14个回答

0

简洁、简短且没有冗余。将数组转换为树形结构:

class Mother {
    private $root;
    public function treeInit($array)
    {
        $this->root = new Child();
        foreach($array as $value){
            $this->root->treeClimb(array_reverse($value));
        }
        return $this->root;
    }
}

class Child {
    private $children = [];
    public function treeClimb($arr)
    {
        if(count($arr) > 0) {
            $childTmp = array_pop($arr);
            if(!key_exists($childTmp,$this->children))
            {
                $this->children[$childTmp] = new Child();
            }
        $this->children[$childTmp]->treeClimb($arr);
        }
    }
}

$array = array(array('obst','banae','krumm','gelb'),
                    array('obst','beere','him'),
                    array('obst','beere','brom'),
                    array('obst','banae','gerade'),
                    array('veg','carot','gerade'));

$obj = new Mother();
var_dump($obj->treeInit($array));

0
在Laravel中,这段代码帮助了我。
<?php
    
    namespace App\Services;
    
    use App\Models\CategoryModel;
    
    class CategoryService
    {
        
        public function getTree(): array
        {
            $categories = CategoryModel::query()->orderBy('sort_category')
                ->select(['id', 'title', 'slug', 'image','parent_id'])
                ->get()->toArray();
            return $this->generateTree($categories);
        }
    
        public function generateTree($elements, $parentId = 0): array
        {
            $result = [];
            foreach ($elements as $element) {
                if ($element['parent_id'] == $parentId) {
                    $children = $this->generateTree($elements, $element['id']);
                    if ($children) {
                        $element['children'] = $children;
                    }
                    $result[$element['id']] = $element;
                    unset($elements[$element['id']]);
                }
            }
            return $result;
        }
    }

0

我想出了一个类似于 @eugen-rieck 的解决方案,想要分享一下。不过我把我的索引数组命名为$branches

$tree = [];
$branches = [];

while (!empty($input)) {
    $beforeCount = count($input);

    foreach ($input as $id => $item) {
        $pid = $item['parent_id'];

        if (isset($branches[$pid])) {
            $branches[$pid]['children'][$id] = $item;
            $branches[$id] = &$branches[$pid]['children'][$id];
            unset($input[$id]);
        }
    }

    if ($beforeCount === count($input)) {
        $firstItem = array_shift($input);
        $id = $firstItem['id'];
        $tree[$id] = $firstItem;
        $branches[$id] = &$tree[$id];
    }
}

0

这是我的解决方案,如果我们假设顶级parent_id=0,则可以完美地工作:

function MakeTree($arr){
    $parents_arr=array();
    foreach ($arr as $key => $value) {
        $parents_arr[$value['pid']][$value['id']]=$value;
    }
    $tree=$parents_arr['0'];
    $this->createTree($tree, $parents_arr);
    return $tree;
}
function createTree(&$tree, $parents_arr){
    foreach ($tree as $key => $value) {
        if(!isset($value['children'])) {
            $tree[$key]['children']=array();
        }
        if(array_key_exists($key, $parents_arr)){
            $tree[$key]['children']=$parents_arr[$key];
            $this->createTree($tree[$key]['children'], $parents_arr);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接