在数组迭代过程中检查当前元素是否为最后一个元素。

88
请帮我将这段伪代码翻译成真正的PHP代码:
 foreach ($arr as $k => $v)
    if ( THIS IS NOT THE LAST ELEMENT IN THE ARRAY)
        doSomething();

编辑:数组可能具有数值或字符串键


6
为什么不使用for循环进行count($arr) - 1次迭代? - Marcin
1
如果您的键是混合的,那么如何确定哪个键是最后一个项目?如果您希望它成为添加到数组中的最后一个项目,则应该有一些数据来指示时间戳。 - Rasika
last的定义:按照数组内部的顺序。这与说foreach循环将选择的最后一个元素相同。 - shealtiel
8个回答

153
你可以使用PHP的end()
$array = array('a' => 1,'b' => 2,'c' => 3);
$lastElement = end($array);
foreach($array as $k => $v) {
    echo $v . '<br/>';
    if($v == $lastElement) {
         // 'you can do something here as this condition states it just entered last element of an array'; 
    }
}

更新1

正如 @Mijoja 指出的那样,如果数组中有多个相同的值,上述代码可能会出现问题。以下是修复方法。

$array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 2);
//point to end of the array
end($array);
//fetch key of the last element of the array.
$lastElementKey = key($array);
//iterate the array
foreach($array as $k => $v) {
    if($k == $lastElementKey) {
        //during array iteration this condition states the last element.
    }
}

更新2

我发现@onteria_提供的解决方案比我之前回答的更好,因为它不会修改数组的内部指针,所以我正在更新答案以匹配他的答案。

$array = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 2);
// Get array keys
$arrayKeys = array_keys($array);
// Fetch last array key
$lastArrayKey = array_pop($arrayKeys);
//iterate array
foreach($array as $k => $v) {
    if($k == $lastArrayKey) {
        //during array iteration this condition states the last element.
    }
}

感谢 @onteria_
更新3
正如 @CGundlach 指出的那样,PHP 7.3 引入了 array_key_last,如果您使用的是 PHP >= 7.3,这似乎是更好的选择。
$array = array('a' => 1,'b' => 2,'c' => 3);
$lastKey = array_key_last($array);
foreach($array as $k => $v) {
    echo $v . '<br/>';
    if($k == $lastKey) {
         // 'you can do something here as this condition states it just entered last element of an array'; 
    }
}

13
如果在数组中有多个相同的值,这会导致问题。 - Mijoja
2
@IbrahimAzharArmar 刚刚发现了这个答案,当我实现你的解决方案时,我注意到自 PHP 7.3 以来,现在有了函数 array_key_last,它也返回数组的最后一个键,而不影响内部指针:https://secure.php.net/array_key_last。这将进一步简化您的解决方案 :) - CGundlach
1
@CGundlach 那很好知道。我会更新答案。谢谢。 - Ibrahim Azhar Armar

27

这对我总是有效

foreach($array as $key => $value) {
   if (end(array_keys($array)) == $key)
       // Last key reached
}

编辑 30/04/15

$last_key = end(array_keys($array));
reset($array);

foreach($array as $key => $value) {
  if ( $key == $last_key)
      // Last key reached
}

为避免 @Warren Sergent 提到的 E_STRICT 警告

$array_keys = array_keys($array);
$last_key = end($array_keys);

2
@Pierce 给你一个提示:这个问题是在被接受的答案之后三年半才得到解答的,而且如果你的数组中有1000个项目,你将会调用"end" 1000次和"array_keys" 1000次。 - StefanNch
如果您正在迭代一个大数组,这显然会存在性能问题。在这种情况下,我的建议是将end(array_keys($array))移动到循环外部。但请确保在迭代之前重置数组。 - Richard Merchant
如果你想要追求严谨,严格模式下,end(array_keys($array)) 会导致一个通知,显示“仅应传递变量的引用” - 要纠正这个问题,需要先定义 $array_keys = array_keys($array),然后在 $array_keys 变量上调用 end()。 - Warren Sergent
@WarrenSergent,或者你可以使用双括号来避免严格提示,https://dev59.com/nHrZa4cB1Zd3GeqP46E3 - Danijel
@Danijel,虽然这是正确的,但我不会依赖于压制或“避免”通知。双括号问题在这里也有一些有趣的讨论,关于这是否可以被视为PHP本身的BUG:https://dev59.com/questions/aGw15IYBdhLWcg3wQ5hi - Warren Sergent

14
$myarray = array(
  'test1' => 'foo',
  'test2' => 'bar',
  'test3' => 'baz',
  'test4' => 'waldo'
);

$myarray2 = array(
'foo',
'bar',
'baz',
'waldo'
);

// Get the last array_key
$last = array_pop(array_keys($myarray));
foreach($myarray as $key => $value) {
  if($key != $last) {
    echo "$key -> $value\n";
  }
}

// Get the last array_key
$last = array_pop(array_keys($myarray2));
foreach($myarray2 as $key => $value) {
  if($key != $last) {
    echo "$key -> $value\n";
  }
}

array_pop 作用于由 array_keys 创建的临时数组,它不会修改原始数组。

$ php test.php
test1 -> foo
test2 -> bar
test3 -> baz
0 -> foo
1 -> bar
2 -> baz

我喜欢这个比被接受的答案更好,因为它只需要在循环外初始化一行。 - Jordan Lev
我更喜欢这个答案,因为它不会改变你即将循环遍历的数组的内部指针。 - autonymous
要对第一个元素执行相同的操作,可以使用 $first = array_shift(array_keys($myarray2)); - Luke
2
这会产生一个 E_STRICT 的提示:运行时提示:只应传递变量的引用。 - Vigintas Labakojis
这似乎是比我的答案更好的方法,我会更新我的答案。 - Ibrahim Azhar Armar

7
为什么不采用这种非常简单的方法:
$i = 0; //a counter to track which element we are at
foreach($array as $index => $value) {
    $i++;
    if( $i == sizeof($array) ){
        //we are at the last element of the array
    }
}

为什么不这样做呢?因为在循环内调用 sizeof() 是没有意义的。数组的大小永远不会改变,那么为什么要一直调用返回计数的函数呢?更重要的是,PHP现在有了 array_key_last(),它更加直接,并且不仅限于处理索引数组。 - mickmackusa

3

我知道这已经很老了,使用SPL迭代器可能只是一种过度设计,但是无论如何,在这里提供另一种解决方案:

$ary = array(1, 2, 3, 4, 'last');
$ary = new ArrayIterator($ary);
$ary = new CachingIterator($ary);
foreach ($ary as $each) {
    if (!$ary->hasNext()) { // we chain ArrayIterator and CachingIterator
                            // just to use this `hasNext()` method to see
                            // if this is the last element
       echo $each;
    }
}

2

我的解决方案也很简单。。。

$array = [...];
$last = count($array) - 1;

foreach($array as $index => $value) 
{
     if($index == $last)
        // this is last array
     else
        // this is not last array
}

只要您的数组键已经自动生成,那么这非常好和简单。 - Matt Kieran
现在已经没有必要再使用这种情境依赖的技术了,因为PHP现在有了array_key_last()函数。请参见被接受的答案。 - mickmackusa

0
如果项目是按数字顺序排列的,请使用key()函数确定当前项目的索引并将其与长度进行比较。您必须使用next()或prev()在while循环中循环遍历项目,而不是在for循环中:
$length = sizeOf($arr);
while (key(current($arr)) != $length-1) {
    $v = current($arr); doSomething($v); //do something if not the last item
    next($myArray); //set pointer to next item
}

1
仅适用于数字或其他严格排序的项目,对于非数字或非严格排序的项目无效。 - shealtiel

0

使用array_keys函数的简单方法是获取键并仅获取反转数组的第一个[0],即最后一个键

$array = array('a' => 1,'b' => 2,'c' => 3);
$last_key = array_keys(array_reverse($array, true))[0];
foreach($array as $key => $value) {
   if ($last_key !== $key)
       // THIS IS NOT THE LAST ELEMENT IN THE ARRAY doSomething();
}

注意array_reverse 函数用于反转数组,它接受两个参数,第一个参数是要反转的数组,第二个参数为 true 时,将反转数组并保留键的顺序


这与仅调用array_key_last()相比,处理过程过多。 - mickmackusa

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