29

在 PHP 5.2 中迭代数组时是否可以“窥视”?例如,我经常使用 foreach 来操作数组中的数据:

foreach($array as $object) {
  // do something
}

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

4

6 回答 6

56

您可以为此目的使用CachingIterator 。

这是一个例子:

$collection = new CachingIterator(
                  new ArrayIterator(
                      array('Cat', 'Dog', 'Elephant', 'Tiger', 'Shark')));

CachingIterator 总是比内部迭代器落后一步:

var_dump( $collection->current() ); // null
var_dump( $collection->getInnerIterator()->current() ); // Cat

因此,当您执行foreachover时$collection,内部 ArrayIterator 的当前元素将已经是下一个元素,允许您查看它:

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

将输出:

Current: Cat - Next:Dog
Current: Dog - Next:Elephant
Current: Elephant - Next:Tiger
Current: Tiger - Next:Shark
Current: Shark

出于某种我无法解释的原因,CachingIterator 将始终尝试将当前元素转换为字符串。如果要遍历对象集合并需要访问属性和方法,CachingIterator::TOSTRING_USE_CURRENT请将其作为第二个参数传递给构造函数。


在旁注中,CachingIterator 之所以得名,是因为它能够缓存它迄今为止迭代过的所有结果。为此,您必须使用 实例化它,CachingIterator::FULL_CACHE然后您可以使用getCache().

于 2010-03-16T21:04:11.137 回答
20

使用array_keys.

$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
    $cur = $array[$keys[$i]];
    $next = $array[$keys[$i+1]];
}
于 2010-03-16T21:05:14.880 回答
8

您可以使用nextandprev来迭代数组。current返回当前项目值和key当前键。

所以你可以做这样的事情:

while (key($array) !== null) {
    next($array); // set pointer to next element
    if (key($array) === null) {
        // end of array
    } else {
        $nextItem = current($array);
    }
    prev($array); // resetting the pointer to the current element

    // …

    next($array);
}
于 2010-03-16T21:03:01.333 回答
4

我知道这是一篇旧帖子,但我现在可以更好地解释当前/下一个/上一个内容。例子:

$array = array(1,2,3,2,5);

foreach($array as $k => $v) {
    // in foreach when looping the key() and current() 
    // is already pointing to the next record
    // And now we can print current
    print 'current key: '.$k.' and value: '.$v;
    // if we have next we can print its information too (key+value)
    if(current($array)) {
         print ' - next key: '.key($array).' and value: '.current($array);
         // at the end we must move pointer to next
         next($array);
    }
    print '<br>';
}

// prints:
// current key: 0 and value: 1 - next key: 1 and value: 2
// current key: 1 and value: 2 - next key: 2 and value: 3
// current key: 2 and value: 3 - next key: 3 and value: 2
// current key: 3 and value: 2 - next key: 4 and value: 5
// current key: 4 and value: 5
于 2012-09-17T19:35:10.063 回答
0

我知道我可以使用 for 循环并通过其索引 ($array[$i+1]) 引用下一项,但它不适用于关联数组。

考虑使用array_values()将关联数组转换为按顺序索引的数组,从而允许您使用简单的 for 循环解决方案。

于 2013-03-12T16:05:01.797 回答
0

旧帖子,但我的两分钱:

如果你想向前看,你真的需要问自己“我是否以最好的方式解决了这个问题”。

您可以解决所有先行问题,而无需进行先行操作。您所需要的只是在集合之前声明的“$prevItem”引用并将其初始化为空。每次循环结束时,将 $prevItem 设置为您刚刚评估的当前数组项。实际上,不是提前达到峰值,而是在第二项开始执行真正的逻辑并使用 $prevItem 引用来执行操作。您通过注意 $prevItem 为空来跳过第一项。

$prevItem = null;
$prevKey = null;

foreach($collection as $key => $val)
{
     if($prevItem != null)
     {
          //do your operation here
     }


     $prevItem = $val;
     $prevKey = $key;
}

它是干净的代码,也是一种常见的模式。

在遍历底层数据结构时,请远离它们……这绝不是好的做法,而且您需要这样做的情况极为罕见。

于 2020-07-10T20:06:42.873 回答