PHP中单个循环中的多个生成器

Mob*_*y04 8 php yield generator

我需要编写一个简单的脚本来加载来自多个文件的数据并以某种方式合并它.但是,鉴于文件可能非常庞大,我想部分加载数据.为此,我决定使用yield.根据示例,我发现我可以使用以下构造用于单个发电机:

$generator = $someClass->load(); //load method uses yield so it returns generator object
foreach($generator as $i) {
  // do something
}
Run Code Online (Sandbox Code Playgroud)

但是如果我想一次使用两台发电机呢?

$generatorA = $someClass1->load(); //load method uses yield so it returns generator object
$generatorB = $someClass2->load(); //load method uses yield so it returns generator object
foreach($generatorA as $i) {
  // how can I access to resultSet from generatorB here?
}
Run Code Online (Sandbox Code Playgroud)

hak*_*kre 18

PHP中的生成器实现了Iterator接口,因此您可以合并/组合多个Generators,就像您可以组合多个Iterators一样.

如果你想一个接一个地迭代两个生成器(合并A + B),那么你可以使用AppendIterator.

$aAndB = new AppendIterator();
$aAndB->append($generatorA);
$aAndB->append($generatorB);

foreach ($aAndB as $i) {
    ...
Run Code Online (Sandbox Code Playgroud)

如果你想一次迭代两个生成器,你可以使用MultipleIterator.

$both = new MultipleIterator();
$both->attachIterator($generatorA);
$both->attachIterator($generatorB);

foreach ($both as list($valueA, $valueB)) {
    ...
Run Code Online (Sandbox Code Playgroud)

这两个包括的例子.示例和警告也在我的博客文章中:

否则我不明白你一直在问什么.如果你能澄清一下,我应该能给你更多指示.


jac*_*ach 8

来自https://www.php.net/manual/en/language.generators.syntax.php#control-structs.yield.from

发电机委托通过yield from

Traversable在 PHP 7 中,生成器委托允许您从另一个生成器、对象或array使用关键字生成值yield from。然后,外部生成器将从内部生成器、对象或数组生成所有值,直到它们不再有效,之后将在外部生成器中继续执行。

因此可以使用 组合两个(或更多)生成器yield from

/**
  * Yield all values from $generator1, then all values from $generator2
  * Keys are preserved
  */
function combine_sequentially(Generator $generator1, Generator $generator2): Generator
{
    yield from $generator1;
    yield from $generator2;
};
Run Code Online (Sandbox Code Playgroud)

或者更奇特的东西(在这里,不可能使用yield from):

/**
  * Yield a value from $generator1, then a value from $generator2, and so on
  * Keys are preserved
  */
function combine_alternatively(Generator $generator1, Generator $generator2): Generator
{
    while ($generator1->valid() || $generator2->valid()) {
        if ($generator1->valid()) {
            yield $generator1->key() => $generator1->current();
            $generator1->next();
        }
        if ($generator2->valid()) {
            yield $generator2->key() => $generator2->current();
            $generator2->next();
        }
    }
};
Run Code Online (Sandbox Code Playgroud)