问题很简单。我有一个foreach循环在我的代码:

foreach($array as $element) {
    //code
}

在这个循环中,当我们在第一次或最后一次迭代时,我希望做出不同的反应。

如何做到这一点?


当前回答

1:为什么不用简单的for语句呢?假设你使用的是一个真实的数组而不是Iterator,你可以很容易地检查counter变量是0还是比元素的总数少1。在我看来,这是最干净、最容易理解的解决方案……

$array = array( ... );

$count = count( $array );

for ( $i = 0; $i < $count; $i++ )
{

    $current = $array[ $i ];

    if ( $i == 0 )
    {

        // process first element

    }

    if ( $i == $count - 1 )
    {

        // process last element

    }

}

2:你应该考虑使用嵌套集来存储你的树结构。此外,您可以通过使用递归函数来改进整个过程。

其他回答

来自@morg的最有效的答案,与foreach不同,它只适用于适当的数组,而不是哈希映射对象。这个答案避免了每次循环迭代都使用条件语句的开销,就像大多数这些答案(包括接受的答案)一样,通过专门处理第一个和最后一个元素,并遍历中间的元素。

array_keys函数可以像foreach一样高效地执行:

$keys = array_keys($arr);
$numItems = count($keys);
$i=0;

$firstItem=$arr[$keys[0]];

# Special handling of the first item goes here

$i++;
while($i<$numItems-1){
    $item=$arr[$keys[$i]];
    # Handling of regular items
    $i++;
}

$lastItem=$arr[$keys[$i]];

# Special handling of the last item goes here

$i++;

我还没有对此进行基准测试,但没有向循环添加逻辑,这是对性能影响最大的地方,因此我怀疑提供有效答案的基准测试非常接近。

如果您想对这类东西进行函数化,我已经在这里尝试了这样一个iterateList函数。不过,如果您非常关心效率,您可能需要对主旨代码进行基准测试。我不确定所有函数调用引入了多少开销。

最简单的方法是

$array = [9,5,6,4,7,8];

$current_iteration = 0;

foreach($array as $item){
  if( 0 === $current_iteration ){
    echo 'this is the first item: ' . $item;
  }

  if( (count($array) - 1) === $current_iteration){
    echo 'this is the last item: ' . $item;
  }

  $current_iteration++;
}
foreach ($arquivos as $key => $item) {
   reset($arquivos);
   // FIRST AHEAD
   if ($key === key($arquivos) || $key !== end(array_keys($arquivos)))
       $pdf->cat(null, null, $key);

   // LAST
   if ($key === end(array_keys($arquivos))) {
       $pdf->cat(null, null, $key)
           ->execute();
   }
}

不确定是否还有必要。但是下面的解决方案应该与迭代器一起工作,并且不需要计数。

<?php

foreach_first_last(array(), function ($key, $value, $step, $first, $last) {
    echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});

foreach_first_last(array('aa'), function ($key, $value, $step, $first, $last) {
    echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});
echo PHP_EOL;

foreach_first_last(array('aa', 'bb', 'cc'), function ($key, $value, $step, $first, $last) {
    echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});
echo PHP_EOL;

function foreach_first_last($array, $cb)
{
    $next = false;
    $current = false;
    reset($array);
    for ($step = 0; true; ++$step) {
        $current = $next;
        $next = each($array);
        $last = ($next === false || $next === null);
        if ($step > 0) {
            $first = $step == 1;
            list ($key, $value) = $current;
            if (call_user_func($cb, $key, $value, $step, $first, $last) === false) {
                break;
            }
        }
        if ($last) {
            break;
        }
    }
}

你也可以使用匿名函数:

$indexOfLastElement = count($array) - 1;
array_walk($array, function($element, $index) use ($indexOfLastElement) {
    // do something
    if (0 === $index) {
        // first element‘s treatment
    }
    if ($indexOfLastElement === $index) {
        // last not least
    }
});

还有三件事需要提一下:

如果你的数组没有严格的索引(数值上),你必须首先通过array_values管道你的数组。 如果你需要修改$元素,你必须通过引用(&$element)传递它。 在匿名函数内部需要的任何外部变量,都必须在use构造中将它们列在$indexOfLastElement旁边,如果需要,同样通过引用。