2009-11-06 12 views
24

todos hemos oído hablar de la forma en un bucle for, debemos hacer esto:¿Cómo se lee una matriz en un bucle foreach de PHP?

for ($i = 0, $count = count($array); $i < $c; ++$i) 
{ 
    // Do stuff while traversing array 
} 

en lugar de esto:

for ($i = 0; $i < count($array); ++$i) 
{ 
    // Do stuff while traversing array 
} 

por razones de rendimiento (es decir, la inicialización $count hubiera llamado count() sólo una vez , en lugar de llamar al count() con cada comprobación condicional).

lo hace luego también hacer una diferencia si, en un bucle foreach, hago esto:

$array = do_something_that_returns_an_array(); 

foreach ($array as $key => $val) 
{ 
    // Do stuff while traversing array 
} 

en lugar de esto:

foreach (do_something_that_returns_an_array() as $key => $val) 
{ 
    // Do stuff while traversing array 
} 

circunstancias asumiendo me permite utilizar cualquiera de los dos? Es decir, ¿PHP llama a la función solo una vez en ambos casos, o es como for donde el segundo caso llamaría a la función una y otra vez?

+8

Ejecuta una prueba! Haga que la función 'do_something_that_returns_an_array()' repita algo internamente. – Artelius

Respuesta

38

foreach() es implemented using iterators - por lo que sólo se llama a la función que devuelve una matriz de una vez, y luego utiliza el iterador que apunta al resultado existente que va a continuar con cada elemento.

8

foreach hace una copia de la matriz de entrada y funciona en eso en cada iteración. Entonces puede usar foreach (do_something_that_returns_an_array() as $key => $val) y llamará al do_something_that_returns_an_array() solo una vez.

+2

Esa redacción no es del todo correcta. Técnicamente, las matrices PHP son de escritura por escritura, por lo que cuando dices que la matriz se copia, la redacción es, en el mejor de los casos, ambigua y, en el peor, engañosa. El valor de retorno simplemente se usa "tal cual". – cletus

0

foreach() funciona con objetos Iterator o IteratorAggregate (por ejemplo, matrices y objetos que implementan la interfaz). No puede funcionar con objetos inmutables. Las funciones devuelven inmutables objetos, por lo que la matriz de volver a tener que ser copiado en objeto iterador antes foreaching (que está hecho por PHP en sí)

+0

inmutable == muy constante :) no se puede cambiar el objeto que devuelve la función en php, no puede ser utilizado por L-Value (f() = 1 falla, tampoco, creo que lo hará array_push (f() , 123)) –

+0

Las funciones no devuelven objetos inmutables. Debido a las particularidades de las referencias a objetos, puede desreferenciar el objeto y hacer 'getObject() -> foo = 'bar'' bastante bien (y si hay una referencia al objeto, se actualiza) ... No se puede matrices de referencia ('getArray() ['foo']' no funciona). Pero no existe tal cosa como un objeto inmutable en PHP. Siempre puede desreferenciar o modificar un objeto (sin restricciones de acceso). – ircmaxell

2

Siempre he asumido que do_something_that_returns_an_array() sólo se ejecuta una vez porque, al contrario que en el bucle, no hay no hay razón para que se ejecute varias veces. La razón por la que el verificador de verdad de bucle for se ejecuta al final de cada iteración es permitir inspectores muy complicados.

Como prueba, hice lo siguiente:

function get_array() {echo 5; return array(1,2,3,4,5);} 
foreach(get_array() as $key => $value) {} 

El caracteres de imprenta 5 una vez. Por lo tanto, la función get_array() solo evalúa una vez.

9

Creo que probarlo seguramente responderá eso.

Aquí está mi código:

function GetArray() { 
    echo "I am called.\n"; 
    return array("One"=>1, "Two"=>2, "Three"=>3, "Four"=>4, "Five"=>5); 
} 

echo "Case #1\n"; 
$array = GetArray(); 
foreach ($array as $key => $val){ 
    // Do stuff while traversing array 
    echo " Inside the loop: $key => $val\n"; 
} 
echo "\n"; 

echo "Case #2\n"; 
foreach (GetArray() as $key => $val) { 
    // Do stuff while traversing array 
    echo " Inside the loop: $key => $val\n"; 
} 
echo "\n"; 

y aquí está el resultado:

 
Case #1 
I am called. 
    Inside the loop: One => 1 
    Inside the loop: Two => 2 
    Inside the loop: Three => 3 
    Inside the loop: Four => 4 
    Inside the loop: Five => 5 

Case #2 
I am called. 
    Inside the loop: One => 1 
    Inside the loop: Two => 2 
    Inside the loop: Three => 3 
    Inside the loop: Four => 4 
    Inside the loop: Five => 5 

Ambos leen la función de llamada una vez. Entonces no diferente.

Cuestiones relacionadas