在PHP中迭代数组时要先行

pak*_*ako 29 php arrays foreach spl

在PHP 5.2中迭代数组时是否有可能"向前看"?例如,我经常使用foreach来操作数组中的数据:

foreach($array as $object) {
  // do something
}
Run Code Online (Sandbox Code Playgroud)

但是我经常需要在通过数组时查看下一个元素.我知道我可以使用for循环并通过它的index($array[$i+1])引用下一个项目,但它不适用于关联数组.我的问题是否有任何优雅的解决方案,可能涉及SPL?

Gor*_*don 52

您可以使用CachingIterator来实现此目的.

这是一个例子:

$collection = new CachingIterator(
                  new ArrayIterator(
                      array('Cat', 'Dog', 'Elephant', 'Tiger', 'Shark')));
Run Code Online (Sandbox Code Playgroud)

CachingIterator总是落后于内部迭代器:

var_dump( $collection->current() ); // null
var_dump( $collection->getInnerIterator()->current() ); // Cat
Run Code Online (Sandbox Code Playgroud)

因此,当您执行此操作foreach$collection,内部ArrayIterator的当前元素将成为下一个元素,允许您查看它:

foreach($collection as $animal) {
     echo "Current: $animal";
     if($collection->hasNext()) {
         echo " - Next:" . $collection->getInnerIterator()->current();
     }
     echo PHP_EOL;
 }
Run Code Online (Sandbox Code Playgroud)

将输出:

Current: Cat - Next:Dog
Current: Dog - Next:Elephant
Current: Elephant - Next:Tiger
Current: Tiger - Next:Shark
Current: Shark
Run Code Online (Sandbox Code Playgroud)

由于某些原因我无法解释,CachingIterator将始终尝试将当前元素转换为字符串.如果要迭代对象集合并需要访问属性方法,CachingIterator::TOSTRING_USE_CURRENT请将第二个参数传递给构造函数.


在旁注中,CachingIterator从缓存到目前为止迭代的所有结果的能力中获取它的名称.要使其工作,您必须使用它进行实例化CachingIterator::FULL_CACHE,然后您可以使用获取缓存的结果getCache().

  • @Psytronic他们真的很整洁.堆叠它们的能力允许非常酷和灵活的东西.遗憾的是,文档记录很少,但请查看http://www.phpro.org/tutorials/Introduction-to-SPL.html (2认同)
  • @pako要么在`MySampleClass`中实现`__toString`方法,要么将`CachingIterator :: TOSTRING_USE_CURRENT`作为CachingIterator构造函数中的第二个参数传递. (2认同)
  • @pako我不知道为什么它需要这一步,但显然确实如此.遗憾的是,Iterators目前记录不清.我给出的解决方案基于使用PHP的Reflection API和Trial and Error.如果您担心Iterator会做一些它不应该做的事情,请确保使用UnitTest. (2认同)

Bar*_*lom 18

使用array_keys.

$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
    $cur = $array[$keys[$i]];
    $next = $array[$keys[$i+1]];
}
Run Code Online (Sandbox Code Playgroud)


Gum*_*mbo 7

您可以使用nextprev迭代数组.current返回当前项值和key当前键.

所以你可以这样做:

while (key($array) !== null) {
    next($array);
    if (key($array) === null) {
        // end of array
    } else {
        $nextItem = value($array);
    }
    prev($array);

    // …

    next($array);
}
Run Code Online (Sandbox Code Playgroud)

  • 代码看起来非常复杂,并且容易出错(太多"nexts/prevs"并且可能发生非常奇怪的事情......). (2认同)