Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 递归迭代器返回额外的元素_Php_Iterator - Fatal编程技术网

Php 递归迭代器返回额外的元素

Php 递归迭代器返回额外的元素,php,iterator,Php,Iterator,RecursiveIteratorIterator如果在之前未调用while循环,则返回额外结果 范例 $array = array("A","B","C"); $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); //$iterator->rewind() ; this would fix it while ( $iterator->valid() ) { print(

RecursiveIteratorIterator
如果在
之前未调用
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
AABC倒带()
while循环需要
  • foreach
    在使用迭代器时,无需调用
    revind
    foreach
  • 之间有什么区别
    
    

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

    foreach
    在使用迭代器时,无需调用
    revind
    即可完美工作
    foreach
    之间有什么区别

    foreach
    在内部调用
    revind()
    ,这就是为什么您不必自己做这件事。这通常是这样做的,因此即使您已经使用了迭代器,
    foreach
    循环也将从头开始。(可以通过将其包装在
    norewindicator
    中来避免这种情况)

    该数组从未被启动或调用。为什么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();
    }
    
    输出看起来有点奇怪,特别是第二次迭代错过了
    next()
    调用,所以它只是停留在同一个元素上

    原因是
    RecursiveIteratorIterator
    实现中的一个特性:迭代器在
    RS\u start
    状态下启动,此状态下的第一个
    next
    调用仅检查
    hasChildren()
    ,而实际上不调用底层迭代器的
    next()
    方法。完成此操作后,它将切换到
    RS\u NEXT
    模式,在该模式下,
    NEXT()
    调用将正常进行。这就是前进步伐被推迟一步的原因


    在我看来,这是一个bug,但事实并非如此。

    它看起来像一个PHP bug。如果你有非常重要的原因知道它,并且这里没有人能够回答,那么试试你在ext/spl/spl_迭代器中的运气吧。cIt还有一些其他迭代器,调用
    valid()
    会产生意想不到的结果,除非迭代器没有正确初始化,这既有调用
    \u construct()
    ,也有
    倒带()
    valid()之前调用。
    可以被调用。如果你不能解决这个问题,你可以使用。如果你不调用rewind,迭代器的行为也会很奇怪。@rambocoder也观察到了这一点。。这看起来更像是一个错误。我把它放在一边,因为我的第一个直觉是,如果我在编写spl,我会对它进行编码(仅转发方法调用),可能有一个bool变量来缓存返回值。但是,当我开始考虑像
    CachingIterator
    这样的东西时,整个迭代器/装饰器范式是否仍然可以与像
    recursiveiterator
    这样的复杂迭代器一起工作,并且异常/错误是否会在疯狂的时刻抛出,这就太复杂了,无法思考一个问题不费吹灰之力的比赛。
    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