Comprobación durante la iteración de la matriz, si el elemento actual es el último elemento

78

Ayúdame a traducir este pseudocódigo a código php real:

 foreach ($arr as $k => $v)
    if ( THIS IS NOT THE LAST ELEMENT IN THE ARRAY)
        doSomething();

Editar: la matriz puede tener claves numéricas o de cadena

shealtiel
fuente
6
¿Por qué no usar forbucle para count($arr) - 1iteraciones?
Marcin
1
Si tiene claves mixtas, ¿cómo se determina qué clave es el último elemento? Si lo desea como el último elemento agregado a la matriz, entonces debe haber algunos datos para indicar una marca de tiempo.
Rasika
definición de último: por el orden interno de la matriz. Lo que es idéntico a decir el último elemento que seleccionará el bucle foreach
shealtiel

Respuestas:

140

puedes usar end () de PHP

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

Actualización1

como lo señaló @Mijoja, lo anterior podría tener problemas si tiene el mismo valor varias veces en la matriz. a continuación se muestra la solución.

$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.
    }
}

Actualización2

Encontré que la solución de @onteria_ es mejor que lo que respondí, ya que no modifica el puntero interno de las matrices, estoy actualizando la respuesta para que coincida con su respuesta.

$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.
    }
}

Gracias @onteria_

Actualización3

Como señaló @CGundlach, se introdujo PHP 7.3, array_key_lastque parece una opción mucho mejor si está utilizando 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'; 
    }
}
Ibrahim Azhar Armar
fuente
11
Esto tendrá problemas si tiene el mismo valor varias veces en la matriz
Mijoja
1
@IbrahimAzharArmar Acabo de encontrar esta respuesta y mientras implementaba su solución noté que desde PHP 7.3 ahora existe la función array_key_last, que también devuelve la última clave de una matriz sin afectar el puntero interno: secure.php.net/array_key_last . Simplificaría su solución aún más :)
CGundlach
1
@CGundlach, es bueno saberlo. Actualizará la respuesta. Gracias.
Ibrahim Azhar Armar
26

Esto siempre me funciona

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

Editar 30/04/15

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

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

Para evitar la advertencia E_STRICT mencionada por @Warren Sergent

$array_keys = array_keys($array);
$last_key = end($array_keys);
Richard Merchant
fuente
mucho más elegante y fácil! :)
Rafael Moni
No estoy seguro de por qué este comentario no es la respuesta aceptada. Es de lejos la más simple / limpia de todas las respuestas proporcionadas y funciona para la gran mayoría de casos de uso potenciales (es decir, matrices asociativas y enumeradas).
Pierce
1
@Pierce para darle una pista: esto fue respondido 3 años y medio después de la respuesta aceptada, además, si tiene 1000 elementos en su matriz, llamará "end" 1000 veces y "array_keys" 1000 veces.
StefanNch
Esto claramente tiene problemas de rendimiento si está iterando sobre una matriz grande. Mi sugerencia en ese caso es mover el final (array_keys ($ array)) fuera del ciclo. Pero asegúrese de restablecer la matriz antes de la iteración.
Richard Merchant
Si quieres ser pedante, en modo estricto, end (array_keys ($ array)) generará un aviso, ya que "Solo las variables deben pasarse por referencia" - para corregir esto, defina $ array_keys = array_keys ($ array) y llame end () en la variable $ array_keys.
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";
  }
}

Dado que array_popfunciona en la matriz temporal creada por array_keys, no modifica la matriz original en absoluto.

$ php test.php
test1 -> foo
test2 -> bar
test3 -> baz
0 -> foo
1 -> bar
2 -> baz
onteria_
fuente
Me gusta esto más que la respuesta aceptada porque solo requiere una línea para la inicialización fuera del ciclo.
Jordan Lev
Me gusta esto más que la respuesta aceptada porque no altera el puntero interno de la matriz que está a punto de recorrer.
Autónomo
hacer lo mismo para el primer elemento$first = array_shift(array_keys($myarray2));
Lucas
2
Esto produce un aviso en E_STRICT: Aviso de tiempo de ejecución: solo las variables deben pasar por referencia
Vigintas Labakojis
Este parece un mejor enfoque que mi respuesta, actualizando mi respuesta.
Ibrahim Azhar Armar
6

Por qué no este método tan simple:

$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
    }
}
PreciousFocus
fuente
2

Sé que esto es antiguo, y usar el iterador SPL tal vez sea una exageración, pero de todos modos, otra solución aquí:

$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;
    }
}
unifreak
fuente
1

Mi solución, también bastante simple ..

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

foreach($array as $index => $value) 
{
     if($index == $last)
        // this is last array
     else
        // this is not last array
}
Edwin Wong
fuente
Esto es bastante agradable y simple, siempre que sus claves de matriz se hayan generado automáticamente.
Matt Kieran
0

Si los elementos están ordenados numéricamente, utilice la función key () para determinar el índice del elemento actual y compararlo con la longitud. Tendría que usar next () o prev () para recorrer los elementos en un ciclo while en lugar de un ciclo 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
}
trusktr
fuente
Porque es lo primero que encontré cuando busqué en Google. Es bueno conocer todas las diferentes formas de hacer lo mismo y estar mejor versado. : D
trusktr
1
No funcionará para artículos que no sean numéricos o que no estén estrictamente ordenados
shealtiel
0
$arr = array(1, 'a', 3, 4 => 1, 'b' => 1);
foreach ($arr as $key => $val) {
    echo "{$key} = {$val}" . (end(array_keys($arr))===$key ? '' : ', ');
}
// output: 0 = 1, 1 = a, 2 = 3, 4 = 1, b = 1
Luca Filosofi
fuente