8

RecursiveIteratorIterator如果在循环rewind()之前没有调用,则返回额外的结果while

例子

$array = array("A","B","C");
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
//$iterator->rewind() ; this would fix it 
while ( $iterator->valid() ) {
    print($iterator->current()) ;
    $iterator->next();
}

输出

AABC  <--- Instead of ABC
  • A为什么没有 额外的C
  • 数组从未启动或调用过为什么$iterator->rewind()需要 while 循环
  • foreach完美地工作,而不必调用迭代器rewind之间foreachwhile使用迭代器时的区别

代码在行动

4

1 回答 1

5

我将按相反的顺序回答问题:

foreach完美地工作,而不必调用rewind它们之间的区别foreach以及while使用迭代器时

foreach在内部调用rewind(),这就是为什么你不必自己做。这总是会完成的,因此即使您已经使用了迭代器,foreach循环也会从头开始。(您可以通过将其包装在 a 中来避免这种情况NoRewindIterator)。

数组从未启动或调用过为什么 while 循环需要 $iterator->rewind()

在这种情况下,SPL 迭代器被设计用于foreach和避免重复的方法调用。如果RecursiveIteratorIterator将在构造时调用该RecursiveArrayIterator::rewind()方法,那么它将在foreach循环开始时再次调用。这就是为什么通话没有结束的原因。

为什么额外的 A 而不是 C ?

要弄清楚这一点,很高兴看到RecursiveArrayIterator实际调用了哪些方法:

<?php

class DebugRAI extends RecursiveArrayIterator {
    public function rewind() { echo __METHOD__, "\n"; return parent::rewind(); }
    public function current() { echo __METHOD__, "\n"; return parent::current(); }
    public function key() { echo __METHOD__, "\n"; return parent::key(); }
    public function valid() { echo __METHOD__, "\n"; return parent::valid(); }
    public function next() { echo __METHOD__, "\n"; return parent::next(); }
}

$array = array("A", "B", "C");
$iterator = new RecursiveIteratorIterator(new DebugRAI($array));
while ($iterator->valid()) {
    echo $iterator->current(), "\n";
    $iterator->next();
}

这会产生以下输出:

DebugRAI::valid
DebugRAI::current
A
DebugRAI::valid
DebugRAI::valid
A
DebugRAI::next
DebugRAI::valid
DebugRAI::valid
DebugRAI::current
B
DebugRAI::next
DebugRAI::valid
DebugRAI::valid
DebugRAI::current
C
DebugRAI::next
DebugRAI::valid
DebugRAI::valid

输出看起来有点奇怪,特别是第二次迭代错过了next()调用,所以它只是停留在同一个元素上。

这样做的原因是RecursiveIteratorIterator实现中的一个特殊性:迭代器从状态开始,并且在该RS_START状态下的第一次next调用只检查hasChildren(),但实际上并不调用底层迭代器的next()方法。完成此操作后,它会切换到调用正确发生的RS_NEXT模式。next()这就是为什么前进的步伐被推迟了一步。

在我看来,这是一个错误,但https://bugs.php.net/bug.php?id=44063声称并非如此。

于 2012-11-25T22:00:46.147 回答