PHP 递归 : Flatten Tree, 保留元数据

标签 php recursion tree adjacency-list

想象一下,您有一棵树代表一个您希望保留在表中但保留嵌套级别的家族。我想将下面的帖子数据放入下面的结构中。

我相信 RecursiveIterator 可能是执行此操作的方法,但我不确定我将如何操作。我有适用于大多数情况的代码,但它已经变得丑陋、臃肿。如果你愿意,我可以发布。

stdClass Object
(
    [name] => Smith
    [type] => Family
    [children] => Array(
            [1] => stdClass Object
                (
                    [name] => Michael
                    [type] => Uncle
                    [children] => Array(
                            [0] => stdClass Object
                                (
                                    [name] => Jared
                                    [type] => cousin
                                )
                        )
                )
            [2] => stdClass Object
                (
                    [name] => Jeff
                    [type] => Dad
                    [children] => Array(
                            [0] => stdClass Object
                                (
                                    [name] => Jonas
                                    [type] => self
                                )
                            [1] => stdClass Object
                                (
                                    [name] => Leah
                                    [type] => sister
                                    [children] => Array(
                                            [0] => stdClass Object
                                                (
                                                    [name] => Jacob
                                                    [type] => nephew
                                                )
                                        )
                                )
                        )
                )
        )
)

持久化的记录应该是这样的:

Array
(
    stdClass Object ( [name] => Smith [type] => Family [subgroup] => 0 [parent_subgroup] => )
    stdClass Object ( [name] => Michael [type] => Uncle [subgroup] => 1 [parent_subgroup] => 0 )
    stdClass Object ( [name] => Jared [type] => Cousin [subgroup] => 2 [parent_subgroup] => 1 )
    stdClass Object ( [name] => Jeff [type] => Dad [subgroup] => 1 [parent_subgroup] => 0 )
    stdClass Object ( [name] => Jonas [type] => self [subgroup] => 3 [parent_subgroup] => 1 )
    stdClass Object ( [name] => Leah [type] => sister [subgroup] => 3 [parent_subgroup] => 1 )
    stdClass Object ( [name] => Jacob [type] => nephew [subgroup] => 4 [parent_subgroup] => 3 )     
)

附言不,我和我姐姐没有 child 。那只是我的类比。 ;)

最佳答案

RecursiveIterator 类可能会有点困惑,我喜欢尽量让它们保持简单。您可以使用 RecursiveIteratorIterator 循环遍历迭代器的值,它甚至可以为您提供当前深度(或在您的情况下为 subgroup)。

这里的挑战是父级不是数组,但我们可以在构造函数中处理它。

<?php
class FamilyIterator implements RecursiveIterator{
    private $data, $counter;

    public function __construct($familyTree){
        $this->data = is_array($familyTree) ? $familyTree : [$familyTree];
    }

    public function current(){
        $row = $this->data[$this->counter];
        return (object)[
            'name' => $row->name,
            'type' => $row->type
        ];
    }

    public function key(){
        return $this->counter;
    }

    public function next(){
        $this->counter++;
    }

    public function rewind(){
        $this->counter = 0;
    }

    public function valid(){
        return $this->counter < count($this->data);
    }

    public function hasChildren(){
        $row = $this->data[$this->counter];
        return isset($row->children);
    }

    public function getChildren(){
        $row = $this->data[$this->counter];
        return new self($row->children);
    }
}

然后你可以像这样使用这个类:

$loop = new RecursiveIteratorIterator(
    new FamilyIterator($dataObj),
    RecursiveIteratorIterator::SELF_FIRST
);

当你在 $loopforeach 时,它会在需要时自动调用 getChildren 方法,所以在 foreach 你将拥有每一行。您甚至可以向 RecursiveIteratorIterator 询问深度。

$newData = [];
foreach($loop as $row){
    $row->subgroup = $loop->getDepth();
    $newData[] = $row;
}

演示:https://eval.in/444078

这可能不是正是您想要的,但希望它能为您指明正确的方向。 RecursiveIterator不需要很复杂。

关于PHP 递归 : Flatten Tree, 保留元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32912994/

相关文章:

javascript - KnockoutJS 和嵌套可排序列表(二维)

haskell - 获取Data.Tree中节点的父级(haskell)

sql - MPTT 表的建议索引

php - 如何使用 OAuth 刷新 token 更新访问 token ?

php - 方法链劫持

java - 通过类层次结构发生尾递归

javascript - html5 canvas pacman 游戏 - javascript 太多递归

php - 将远程数据库 (mysql) 与 sqlite 数据库同步,反之亦然

php - 日期年份错误

java - 打印具有多个子节点的数据 [Java]