RecursiveIteratorIterator返回额外的元素 [英] RecursiveIteratorIterator returns extra elements
问题描述
RecursiveIteratorIterator
返回额外的结果
示例
$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
? - 该数组从未启动或调用过,为什么while循环需要
$iterator->rewind()
-
foreach
可以完美地工作,而不必调用rewind
与迭代器一起使用时foreach
和while
之间的区别是什么 - Why an extra
A
notC
? - The Array has never been initiated or called why is
$iterator->rewind()
required for while loop foreach
works perfectly without having to callrewind
whats the differences betweenforeach
andwhile
when working with iterators
推荐答案
我将以相反的顺序回答问题:
I'm going to answer the questions in reverse order:
foreach
可以完美地工作,而不必调用rewind
与迭代器一起工作时foreach
和while
之间的区别是什么
foreach
works perfectly without having to callrewind
whats the differences between thoseforeach
andwhile
when working with iterators
foreach
在内部对rewind()
进行调用,这就是为什么您不必自己执行此操作的原因.总是这样做,因此,即使您已经使用过迭代器,foreach
循环也将从头开始. (您可以通过将其包装在NoRewindIterator
中来避免这种情况.)
foreach
internally does a call to rewind()
, that's why you don't have to do it yourself. This is always done, so even if you have already used an iterator, the foreach
loop will start over from the beginning. (You can avoid this by wrapping it in a NoRewindIterator
).
从未初始化或调用该数组,为什么while循环需要$ iterator-> rewind()
The Array has never been initiated or called why is $iterator->rewind() required for while loop
SPL迭代器设计为与foreach
一起使用,并且在这种情况下避免重复的方法调用.如果RecursiveIteratorIterator
在构造时调用RecursiveArrayIterator::rewind()
方法,则在foreach
循环开始时将再次调用它.这就是为什么通话未完成的原因.
The SPL iterators are designed to be used with foreach
and to avoid duplicate method calls in this case. If the RecursiveIteratorIterator
would call the RecursiveArrayIterator::rewind()
method on construction, then it would be called again when the foreach
loop starts. That's why the call isn't done.
为什么额外的A不是C?
Why an extra A not C ?
要弄清楚这一点,很高兴看到RecursiveArrayIterator
的哪些方法实际被调用:
To figure this out it is nice to see which methods of the RecursiveArrayIterator
actually get called:
<?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()
调用,因此它只是停留在同一元素上.
The output looks a bit odd, in particular the second iteration misses the next()
call, so it just stays at the same element.
这样做的原因是RecursiveIteratorIterator
实现中的特殊性:迭代器以RS_START
状态开始,并且在此状态下的第一个next
调用仅检查hasChildren()
,但实际上并未调用基础迭代器的next()
方法.完成此操作后,它会切换到RS_NEXT
模式,在该模式下next()
调用会正确进行.这就是为什么向前移动被延迟一步的原因.
The reason for this is a peculiarity in the RecursiveIteratorIterator
implementation: Iterators start off in the RS_START
state and the first next
call in this state only checks hasChildren()
, but does not actually call the underlying iterator's next()
method. After this was done it switches into the RS_NEXT
mode in which the next()
call happens properly. That's why the forward move is delayed by one step.
在我看来,这是一个错误,但是 https://bugs.php.net/bug.php?id=44063 另行声明.
In my eyes this is a bug, but https://bugs.php.net/bug.php?id=44063 claims otherwise.
这篇关于RecursiveIteratorIterator返回额外的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!