代码之家  ›  专栏  ›  技术社区  ›  goat

为什么要倒带迭代器

  •  1
  • goat  · 技术社区  · 14 年前
    $arrayIter = new ArrayIterator( array(1, 2) );
    $iterIter = new IteratorIterator($arrayIter);
    
    var_dump($iterIter->valid()); //false
    var_dump($arrayIter->valid()); //true
    

    如果我第一次打电话 $iteriter->倒带() 然后 $ITeriter->有效() 是真的。我很好奇为什么需要调用rewind()。我认为这是有充分理由的,但是我希望它只在它的内部迭代器处于的任何状态下开始迭代,并在开始迭代之前让它作为一个选项返回。

    调用next()似乎也使它处于“有效”状态(尽管它前进到下一个位置,表明它以前在第一个位置)。

    $arrayIter = new ArrayIterator(array(1,2));
    $iterIter = new IteratorIterator($arrayIter);
    
    $iterIter->next();
    var_dump($iterIter->valid()); 
    

    同样,我很好奇为什么我需要调用rewind(),尽管内部迭代器处于有效状态。

    3 回复  |  直到 12 年前
        1
  •  5
  •   johannes    14 年前

    对于一个新的迭代器,位置没有初始化,仅仅是出于性能原因,您可以将迭代器堆叠在其他迭代器之上,如果所有迭代器在构造期间都会倒带,则会对性能产生一些影响,此外,一些迭代器可能会在constr之后更改其第一个值。已经执行了UCtor—迭代器还不知道这一点。

    迭代器通常由foreach()执行,foreach()首先执行rewind()。

        2
  •  2
  •   hakre    12 年前

    在扩展 IteratorIterator 类以备用实现整个迭代器接口和/或创建一个迭代器的修饰符。

    这个装饰器已经是解决问题的解决方案,它只需要实现缺失的功能来消除不一致性。无需自动倒带:

    class IteratorDecorator extends IteratorIterator
    {
        public function valid()
        {
            return $this->getInnerIterator()->valid();
        }
    }
    

    示例:如果您有 Iterator 默认情况下有效的对象,例如 ArrayIterator :

    $it = new ArrayIterator(array(1));
    var_dump($it->valid());             # bool(true)
    
    $itit = new IteratorIterator($it);
    var_dump($itit->valid());           # bool(false)
    

    这表明 迭代器 实施得好, 迭代器 对象不能正确反映内部 阵列振荡器 的状态。使用 IteratorDecorator 可以治愈:

    $decor = new IteratorDecorator($it);
    var_dump($decor->valid());          # bool(true)
    

    如果你一直跟踪到这里,这里有另一个你可能想考虑的特殊情况:如果你不需要 rewind 使用内部迭代器,您只需使用 NoRewindIterator 它也返回正确的有效性:

    $noretit = new NoRewindIterator($it);
    var_dump($noretit->valid());        # bool(true)
    

    考虑到约翰内斯的“不自动倒带”论点,这是有意义的,因为 无指示器 预期迭代器不应重绕,并正确显示内部迭代器的有效性。

    但是作为 迭代器 显示,我不做任何类型的自动倒带以及消除不一致。

        3
  •  0
  •   Gordon Haim Evgi    14 年前

    正如@johannes所说,位置在 IteratorIterator 因此,在对其运行任何其他方法或将其与foreach()一起使用之前,它是无效的

    试着去做

    var_dump( $iterIter->current() ); // NULL
    var_dump( $iterIter->getInnerIterator()->current() ); // 1
    

    以及

    $iterIter->rewind();
    var_dump( $iterIter->current() ); // 1
    var_dump( $iterIter->getInnerIterator()->->current() );  // 1
    

    还要注意,在一个统一的迭代器上:

    $iterIter->next(); // 2
    var_dump( $iterIter->current()) ; // 2 (from NULL to 2)
    var_dump( $iterIter->getInnerIterator()->current() );  // 2
    

    注意 $arrayIter 从您的代码片段来看 $iterIter->getInnerIterator() .

    希望能照亮你。