2011-01-21 12 views
5

Estoy haciendo un sistema de advertencia de estilo 'semáforo' de PHP para mi sitio web, que básicamente dice 'si hay un cambio porcentual X entre la entrada de la matriz actual y la siguiente, arroje un error'.Extraiga elementos del siguiente artículo foreach en PHP?

Por lo tanto, estoy recorriendo mis elementos de matriz en un bucle foreach, sin embargo, tengo que ser capaz de hacer algo como esto: (nota: esto es solo un ejemplo básico, pero debería ser suficiente para obtener la idea)

foreach($array as $a) 
{ 
$thisValue = $a['value']; 
$nextValue = next($a['value']); 

$percentageDiff = ($nextValue-$thisValue)/$thisValue; 
} 

He puesto las etiquetas next() para obtener el siguiente valor, pero entiendo que esto solo funciona para las matrices. ¿Hay algo más que pueda usar para obtener el próximo artículo foreach?

¡Gracias por su tiempo!

+0

posible duplicado de [Peek delante cuando se repite una matriz en PHP 5.2] (http://stackoverflow.com/questions/2458099/peek-ahead-when-iterating-an-array-in-php-5-2) – Gordon

+0

Gracias por las respuestas, todas parecían formas realmente geniales de hacer esto. Opté por la solución provista por @Orbling y @contagious: si bien causa una sobrecarga muy modificada, puedo aceptar la frecuencia con la que se llamará a la función. – Sk446

Respuesta

10

hágalo de la otra manera y almacene la entrada anterior y compárelas.

$prev = null; 
foreach ($item as $i){ 
    if ($prev !== null){ 
     diff($prev, $i); 
    } 
    $prev = $i 
} 
+0

He votado, esto es lo que haría. (¡pero revise sus corchetes!) –

+0

Creo que esta solución tiene una sobrecarga innecesaria;) –

+0

@Brandon gracias, fijo – helloandre

4

Respuesta simple: no utilice un lazo foreach. Utilizar un simple bucle for lugar:

for ($i = 0; $i < count($array); $i++) { 
    if (isset($array[$i + 1])) { 
     $thisValue = $array[$i]['value']; 
     $nextValue = $array[$i + 1]['value']; 

     $percentageDiff = ($nextValue-$thisValue)/$thisValue; 
    } 
} 
+1

Esto no funciona para matrices asociativas como diccionarios y hashtables, ¿verdad? –

+0

@Brandon Sí, correcto. – lonesomeday

1

usted debería ser capaz de utilizar:

foreach($array as $a) 
{ 
    $array_copy = $array; 
    $thisValue = $a['value']; 

    $nextValue = next($array_copy); 
    $nextValue = $nextValue['value']; 

    $percentageDiff = ($nextValue-$thisValue)/$thisValue; 
} 

Esto copia la matriz y luego se mueve el puntero a lo largo de 1.

1

La solución más sencilla es la OMI para cambiar tu forma de pensar En lugar de inspeccionar el registro actual y el siguiente, inspeccione el registro anterior y el actual. Recordar el anterior es más fácil que obtener el siguiente.

Si usted no quiere eso, también puede deshacerse de la foreach e iterar C-estilo usando for y una variable de contador - uno cavet sin embargo: matrices dispersas de PHP pueden morder, por lo que mejor llamada array_values() en la matriz inspeccionados antes de iterar

1

Si desea trabajar con foreach, se podría comparar el valor actual con el valor anterior en lugar de con el siguiente valor:

$previous = null; 
foreach ($array as $a) { 
    if (!is_null($previous)) { 
     $thisValue = $previous['value']; 
     $nextValue = $a['value']; 
     $percentageDiff = ($nextValue-$thisValue)/$thisValue; 
    } 
    $previous = $a; 
} 

Con ello sólo cambia toda la iteración por un item.

1

¿Por qué no utilizar simplemente un bucle normal for en lugar del iterador foreach?

<?php 
    $testArray = array(10,20,30,40,50,60,70,80,90,100); 

    $elementCount = count($testArray); 
    for($loop=0; $loop<$elementCount; $loop++) { 

     $thisValue = $testArray[$loop]; 

     // Check if there *is* a next element. 
     $nextValue = $loop + 1 < $elementCount ? $testArray[$loop + 1] : null; 

     // Calculate the percentage difference if we have a next value. 
     if($nextValue) $percentageDiff = ($nextValue-$thisValue)/$thisValue; 
    } 
?> 
+1

Esto no funciona para matrices asociativas como diccionarios y hashtables, ¿verdad? –

+0

@Brandon Tendría que extraer las array_keys e iterar usando aquellas en esa instancia. –

+0

@Brandon Incidentalmente, solo estaba delineando una ruta potencial, esta (y de hecho todas las otras hasta la fecha) obviamente no son implementaciones utilizables, ya que pisan felizmente todo el 'porcentaje de diferencia' cada vez que iteran. :-) –

1

'por lo general es más fácil utilizar el valor anterior de la siguiente:

$lastValue = NULL; 
foreach ($array as $a) { 
    if ($lastValue === NULL) { 
     $lastValue = $a['value']; 
     continue; 
    } 

    $percentageDiff = ($a['value'] - $lastValue)/$lastValue; 

    $lastValue = $a['value']; 
} 
+0

El valor anterior funcionaría, eso lo hará mucho más fácil en realidad ... no estoy seguro de por qué no pensé en eso :) – Sk446

1
for($i=0;$i<count($array);$i++) { 
$thisValue = $array[$i]; 
$nextValue = $array[i+1]; // will not be set if $i==count($array)-1 
$percentageDiff = ($nextValue-$thisValue)/$thisValue; 
} 

de hecho hay array iterator funciones que apoyan lo que necesita, y también simplemente bucle thorugh una matriz con next()/prev() etc funciona bien, pero la solución anterior es más elegante

No funciona con foreach porque foreach crea una copia de las referencias y no establece los punteros de matriz en th e matriz en sí.

Este es un ejemplo que se puede utilizar para matrices asociativas usando funciones de matriz iterador:

$arrayobject = new ArrayObject($array); 
$iterator = $arrayobject->getIterator(); 

     for($i=0;$i<count($array);$i++) { 
      $iterator->seek($i); 
      $thisValue = $iterator->current(); 
      $iterator->seek($i+1); 
      $nextValue = $iterator->current(); 
      $percentageDiff = ($nextValue-$thisValue)/$thisValue; 
     } 
+0

Esto no funciona para matrices asociativas como diccionarios y hashtables, ¿verdad? –

+0

eso es correcto, por eso he vinculado las funciones del iterador de matriz que son perfectamente adecuadas. Otra posibilidad es recordar el último elemento de la matriz y calcular en función de eso y cambiar el resultado por una entrada. Agregué un código de muestra a la respuesta. –

Cuestiones relacionadas