RecursiveIteratorIterator返回额外的元素 [英] RecursiveIteratorIterator returns extra elements

查看:76
本文介绍了RecursiveIteratorIterator返回额外的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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与迭代器一起使用时foreachwhile之间的区别是什么
    • Why an extra A not C ?
    • The Array has never been initiated or called why is $iterator->rewind() required for while loop
    • foreach works perfectly without having to call rewind whats the differences between foreach and while when working with iterators
    • 运行中的代码

      推荐答案

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

      I'm going to answer the questions in reverse order:

      foreach可以完美地工作,而不必调用rewind与迭代器一起工作时foreachwhile之间的区别是什么

      foreach works perfectly without having to call rewind whats the differences between those foreach and while 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆