chumkiu的答案是正确的。一些额外的想法。
建议 0:剩余() 装饰器。
(这是我在这里添加的最新版本,但可能是最好的)
7+菲律宾比索:
function remaining(\Generator $generator) {
yield from $generator;
}
PHP 5.5+ < 7:
function remaining(\Generator $generator) {
for (; $generator->valid(); $generator->next()) {
yield $generator->current();
}
}
用法(所有 PHP 版本):
function foo() {
for ($i = 0; $i < 5; ++$i) {
yield $i;
}
}
$gen = foo();
if (!$gen->valid()) {
// Not even the first item exists.
return;
}
$first = $gen->current();
$gen->next();
$values = [];
foreach (remaining($gen) as $value) {
$values[] = $value;
}
可能存在一些间接寻址开销。但从语义上讲,我认为这是相当优雅的。
建议1:for()而不是while()。
作为一个很好的语法替代方案,我建议使用而不是减少调用和初始化的混乱。for()
while()
->next()
简单版本,没有您的初始值:
for ($gen = generator(); $gen->valid(); $gen->next()) {
echo $gen->current();
}
使用初始值:
$gen = generator();
if (!$gen->valid()) {
echo "Not even the first value exists.<br/>";
return;
}
$first = $gen->current();
echo $first . '<br/>';
$gen->next();
for (; $gen->valid(); $gen->next()) {
echo $gen->current() . '<br/>';
}
你可以把第一个放到语句中,但我认为这不会增加太多的可读性。$gen->next()
for()
我在本地(PHP 5.6)做了一个小的基准测试,表明这个带有for()或while()的版本与显式调用->next(),current()等的版本比带有的隐式版本慢。foreach(generator() as $value)
建议 2:生成器() 函数中的偏移参数
这仅在您控制生成器函数时才有效。
function generator($offset = 0) {
if ($offset <= 0) {
yield 'First value';
$offset = 1;
}
for ($i = $offset; $i <= 3; $i++) {
yield $i;
}
}
foreach (generator() as $firstValue) {
print "First: " . $firstValue . "\n";
break;
}
foreach (generator(1) as value) {
print $value . "\n";
}
这意味着任何初始化都将运行两次。也许不可取。
此外,它还允许像generator(9999)这样的调用,具有非常高的跳过数。例如,有人可以用它来以块的形式处理生成器序列。但是,每次从 0 开始,然后跳过大量项目,在性能方面似乎是一个坏主意。例如,如果数据来自文件,则跳过意味着读取+忽略文件的前9999行。