需要迭代器建议来遍历树

时间:2012-06-08 20:15:32

标签: php iterator spl

嗨,我需要一些迭代器建议。

我有一个Category对象,它可以包含一组项目,也可以有子类别。

从Doctrine ORM我得到了一个类别对象的集合。现在我想遍历这个集合并展平类别树结构。因此,子类别与其父级处于同一级别。我也想过滤孩子们。

也许有人可以指出我正确的方向,目前在Iterator云中有点迷失。

<?php

class Category
{
    private $name;

    private $children;

    private $type;

    private $parent;

    private $items;

    //parent category
    public function getParent()
    {
        return $this->parent;
    }

    public function setItems($items)
    {
        $this->items = $items;
    }


    public function getItems()
    {
        return $this->items;
    }

    //colelction of categories
    public function getChildren()
    {
        return $this->children;
    }
}

2 个答案:

答案 0 :(得分:4)

您只需要实现RecursiveIterator界面。然后,您可以使用具体的RecursiveIteratorIterator迭代它。

帮助您理解......

RecursiveIterator本身并不是非常“递归”。它只是提供某些可用于获取子项的方法的东西(递归中的子问题可以被认为是“子”)。请注意,RecursiveIterator.getChildren()必须以另一个RecursiveIterator的形式返回其子项。

你可以手动迭代一个普通的RecursiveIterator,但是,跟踪递归调用getChildren返回的所有子迭代器并保持适当的深度等将是非常痛苦的。 。RecursiveIteratorIterator进来的.thats

RecursiveIteratorIterator是实际工作系统地遍历结构,模仿递归的东西。它迭代RecursiveIterator就好像它是一个平面列表,但是在列表中的每个元素上,它测试当前元素是否存在子节点。如果是hasChildren,则调用getChildren并将对此新的子迭代器的引用存储在堆栈中。它以一种提供您期望的递归行为的方式管理堆栈(与手动将递归函数转换为迭代版本的方式非常相似)。

要清楚,你不要编写自己的RecursiveIteratorIterator代码,只是实例化php的具体实现。这个类纯粹是为了隐藏复杂性并管理在遍历过程中实例化的所有许多RecursiveIterator对象,并将遍历结果呈现给看似平坦的列表。 RecursiveIteratorIterator内部是一个非常复杂的类。

至于过滤 -

有几种方法。为了便于使用,如果你有php 5.4,我建议使用CallbackFilterIterator。否则,您必须延长FilterIterator

但是,这两个元素在递归结构的视图已被展平为类似结构的列表之后过滤掉元素。因此,您的过滤器不能例如说“跳过整个子树”,它只能说“跳过这个单个元素”。如果您需要说“跳过整个子树”,如果您没有php 5.4,则需要使用RecursiveCallbackFilterIterator或扩展RecursiveFilterIterator

你可能想从

开始
class RecursiveCategoryIterator implements RecursiveIterator {...

那应该包含一个Category对象列表。

答案 1 :(得分:0)

你必须从根节点开始recursively traverse每个$this->getChildren()(节点和子节点(及其子节点(及其子节点(及其子节点))))(递归)直到它是null。这将导致类似这样的事情:

(Start)
Root node
-> 1st Child node
--> Grandchild node
-> 2nd Child node
-> 3rd Child node
-> 4th Child node
--> Grandhild node
(No more children so exit)