PHP如何确定foreach循环中的第一个和最后一个迭代?

613

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

foreach($array as $element) {
    //code
}
在这个循环中,我想在第一次或最后一次迭代时有不同的反应。如何实现?

你应该使用PHP更新问题。Javascript也有forEach循环。观众可能会得到误导性的答案。 - Maidul
@Maidul 确实,在谷歌上并不清楚它是关于 PHP 的,所以我在标题中添加了“PHP”一词以增加清晰度。 - Hasen
21个回答

6

对于生成SQL查询脚本或任何针对第一个或最后一个元素执行不同操作的内容,避免使用不必要的变量检查可以提高速度(几乎快两倍)。

目前被接受的解决方案使用了循环和循环内的检查,每次迭代都会进行一次检查,正确(快速)的做法是:

$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
    $some_item=$arr[$i];
    $i++;
}
$last_item=$arr[$i];
$i++;

一个小巧的自制基准测试显示如下:

测试1:运行模型morg 100000次

时间:1869.3430423737毫秒

测试2:运行模型if last 100000次

时间:3235.6359958649毫秒

很明显,这个检查代价非常高,当然,你添加的变量检查越多,情况就会变得更糟糕 ;)


只有在确保具有递增整数键时,您的代码才能正常工作。 `$arr = array('one' => "1 1 1", 4 => 'Four', 1 => 'One');$numItems = count($arr); $i=0; $firstitem=$arr[0]; echo $i . ': ' . $firstitem . ", "; $i++; while($i<$numItems-1){ $some_item=$arr[$i]; echo $i . ': ' . $some_item . ", "; $i++; } $last_item=$arr[$i]; echo $i . ': ' . $last_item . ", "; $i++;将输出:0: , 1: One, 2: ,` - Seika85
将哈希映射转换为数组是未定义的行为,所创建的“Object”数组为{'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"},但空元素在计数时被忽略,你正在计算已定义的“things”的数量!赏金即将到来!这个答案值得获得赏金,但如果@Morg.离开了,那就没有意义了。我会把赏金给一个可能不会再使用SO的人!如果他回来并改进了他的答案,他应该得到赏金! - mjz19910
正如 @mjz19910 所指出的那样,哈希映射和数组并不是可以互相替代的。然而,您可以使用 array_keys 函数获取哈希映射的属性,这个属性您可以像数组一样进行操作。请参见我的“改进”答案 - TheMadDeveloper
这是我用于查询的代码:$querySet = ""; foreach ($fieldSet as $key=>$value) { $value = $db->dbLink->quote($value); $querySet .= "$key = $value, "; } $querySet = substr_replace($querySet, "", -2); $queryString = "UPDATE users SET $querySet WHERE user_ID = '$user_ID'"; - Rovshan Mamedov

5

即使你想要检查一个$value的第一次出现,使用布尔变量仍然是最可靠的方法 (在我的情况和许多情况下,我发现这更有用),像这样:

$is_first = true;

foreach( $array as $value ) {
    switch ( $value ) {
        case 'match':
            echo 'appeared';

            if ( $is_first ) {
                echo 'first appearance';
                $is_first = false;
            }

            break;
        }
    }

    if( !next( $array ) ) {
        echo 'last value';
    }
}

那么如何使用!next( $array )查找最后一个$value,如果没有要迭代的next()值,则返回true
如果我要使用计数器,我更喜欢使用for循环而不是foreach,像这样:
$len = count( $array );
for ( $i = 0; $i < $len; $i++ ) {
    $value = $array[$i];
    if ($i === 0) {
        // first
    } elseif ( $i === $len - 1 ) {
        // last
    }
    // …
    $i++;
}

5

对于键和值,这同样有效:

foreach ($array as $key => $value) {
    if ($value === end($array)) {
        echo "LAST ELEMENT!";
    }
}

3
这样你正在比较值,如果一个数组包含两个相同的元素,它将无法起作用。 - Krzysztof Przygoda

4
使用 reset($array)end($array)
<?php

    $arrays = [1,2,3,4,5];

    $first  = reset($arrays);
    $last   = end($arrays);    

    foreach( $arrays as $array )
    {

        if ( $first == $array )
        {
            echo "<li>{$array} first</li>";
        }
        else if ( $last == $array )
        {
            echo "<li>{$array} last</li>";
        }
        else
        {
            echo "<li>{$array}</li>";
        }                

    }

演示示例 repl.it


4

我看到了这个帖子,因为我也遇到了同样的问题。我只需要获取第一个元素,然后重新分析我的代码,直到我想到这个方法。

$firstElement = true;

foreach ($reportData->result() as $row) 
{
       if($firstElement) { echo "first element"; $firstElement=false; }
       // Other lines of codes here
}

上述代码非常完整,但如果你只需要第一个元素,可以尝试使用以下代码。

2

不确定是否仍然需要。但是以下解决方案应该适用于迭代器,并且不需要 count

<?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;
        }
    }
}

1
你也可以使用匿名函数:

$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,你必须通过引用传递它(&$element)。
  • 如果你需要在匿名函数中使用外部变量,你必须将它们与 $indexOfLastElement 列在 use 结构的旁边,如果需要,也要通过引用传递。

0

最简单的方法是:

$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++;
}

0

您可以使用计数器和数组长度。

    $array = array(1,2,3,4);
$i = 0; $len = count($array); foreach ($array as $item) { if ($i === 0) { // 第一个 } else if ($i === $len - 1) { // 最后一个 } // … $i++; }

0
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();
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接