在PHP中可以使用多个迭代器吗?

art*_*olk 4 php iterator design-patterns

请给VolkerK检查答案,他提供了另一种解决方案,但我不能将两个帖子标记为答案.:(


美好的一天!

我知道C#允许使用yield的多个迭代器,如下所述: c#中是否可以使用多个迭代器?

在PHP中有和Iterator接口.是否可以为类实现多个迭代方案?

更多细节(编辑):

例如,我有类TreeNode实现单树节点.整个树只能使用一个这个类来表示.我想提供迭代器来迭代当前节点的所有直接和间接子节点,例如使用BreadthFirst或DepthFirst顺序.

我可以将这个Iterators实现为单独的类,但这样做我需要树节点将它的子集合公开为public.

C#伪代码:

 public class TreeNode<T> 
  {
  ...
     public IEnumerable<T> DepthFirstEnumerator
     {
         get
        {
            // Some tree traversal using 'yield return'
        }
     }

     public IEnumerable<T> BreadthFirstEnumerator
     {
         get
         {
             // Some tree traversal using 'yield return'
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)

use*_*291 5

是的你可以.

foreach(new IteratorOne($obj) as $foo) ....

foreach(new IteratorTwo($obj) as $bar) .....
Run Code Online (Sandbox Code Playgroud)

实际上,只要您的类实现了Iterator,就可以将任意IteratorIterator应用于它.这是一件好事,因为应用元迭代器不需要知道有关该类的任何信息.

例如,考虑一个像这样的可迭代类

class JustList implements Iterator
{
    function __construct() { $this->items = func_get_args(); }
    function rewind()      { return reset($this->items); }
    function current()     { return current($this->items); }
    function key()         { return key($this->items); }
    function next()        { return next($this->items); }
    function valid()       { return key($this->items) !== null; }
}
Run Code Online (Sandbox Code Playgroud)

让我们定义一些元迭代器

class OddIterator extends FilterIterator {
    function accept() { return parent::current() % 2;  }
}

class EvenIterator extends FilterIterator {
    function accept() { return parent::current() % 2 == 0;  }
}
Run Code Online (Sandbox Code Playgroud)

现在将元迭代器应用于基类:

 $list = new JustList(1, 2, 3, 4, 5, 6, 7, 8, 9);

 foreach(new OddIterator($list) as $p) echo $p;  // prints 13579
 foreach(new EvenIterator($list) as $p) echo $p; // prints 2468
Run Code Online (Sandbox Code Playgroud)

更新:php没有内部类,所以你在这里运气不好,至少没有求助于eval.您的迭代器需要是单独的类,它们知道基类结构.通过在基类中提供实例化后台迭代器的方法,可以降低其危害:

 class TreeDepthFirstIterator implements Iterator 
 {
      function __construct($someTree).....
 }


 class Tree
 {
       function depthFirst() { return new TreeDepthFirstIterator($this); }
        ....
 }


 foreach($myTree->depthFirst() as $node).....
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用lambdas而不是foreach.这更好,更灵活,但需要php5.3:

 class Tree
 {
        function depthFirst($func) {
              while($node = .....)
                $func($node);

 .....

 $myTree->depthFirst(function($node) {
     echo $node->name;
 });
Run Code Online (Sandbox Code Playgroud)