PHP - 迭代两次通用可迭代对象

问题描述 投票:0回答:2

在 PHP 7.1 中,有一个新的 iterable 伪类型,它抽象数组和

Traversable
对象。

假设在我的代码中我有一个如下所示的类:

class Foo
{
    private $iterable;

    public function __construct(iterable $iterable)
    {
        $this->iterable = $iterable;
    }

    public function firstMethod()
    {
        foreach ($this->iterable as $item) {...}
    }

    public function secondMethod()
    {
        foreach ($this->iterable as $item) {...}
    }
}

如果

$iterable
是数组或
Iterator
,则效果很好,除非
$iterable
Generator
。事实上,在这种情况下,调用
firstMethod()
然后调用
secondMethod()
将产生以下
Exception: Cannot traverse an already closed generator

有办法避免这个问题吗?

php iterator generator iterable
2个回答
4
投票

发电机不能倒带。如果你想避免这个问题,你必须制作一个新的发电机。如果您创建一个实现 IteratorAggregate 的对象,这可以自动完成:

class Iter implements IteratorAggregate
{
    public function getIterator()
    {
        foreach ([1, 2, 3, 4, 5] as $i) {
            yield $i;
        }
    }
}

然后只需传递该对象的实例作为迭代器:

$iter = new Iter();
$foo = new Foo($iter);
$foo->firstMethod();
$foo->secondMethod();

输出:

1
2
3
4
5
1
2
3
4
5

0
投票

经过一番研究,我发现:

  • 非工作本机CachingIterator,它只将值保留在内部,但不会在连续迭代中返回它们。
  • 来自
  • loophp/iterators 库的精彩的
    CachingIteratorAggregate
    。它所做的事情与我们期望的完全相同 - 保留迭代结果并在第二次迭代时返回它们。

因此,请考虑查看 https://github.com/loophp/iterators

© www.soinside.com 2019 - 2024. All rights reserved.