2011-01-21 10 views
5

Sto facendo un sistema di avviso in stile "semaforo" PHP per il mio sito web, che in pratica dice "se c'è una variazione percentuale in X tra la voce dell'array corrente e quella successiva, genera un errore".Estrarre elementi dal prossimo articolo foreach in PHP?

Quindi, eseguo il ciclo degli elementi del mio array in un ciclo foreach, tuttavia devo essere in grado di fare qualcosa del genere: (nota: questo è solo un esempio di base, ma dovrebbe essere sufficiente per ottenere l'idea)

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

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

Ho messo tag next() per ottenere il valore successivo ma capisco che questo funziona solo per gli array. C'è qualcos'altro che posso usare per ottenere il prossimo articolo foreach?

Grazie per il vostro tempo!

+0

possibile duplicato [Peek anticipo quando l'iterazione un array in PHP 5.2] (http://stackoverflow.com/questions/2458099/peek-ahead-when-iterating-an-array-in-php-5-2) – Gordon

+0

Grazie per le risposte - tutto sembrava davvero un ottimo modo per ottenere questo risultato. Ho optato per la soluzione fornita da @Orbling e @contagious - Anche se causa un overhead molto modesto, posso convivere con quella data con quale frequenza verrà chiamata la funzione. – Sk446

risposta

10

fare l'altro modo e memorizzare la voce precedente e confrontarli.

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

Ho votato, questo è quello che vorrei fare. (ma controlla le parentesi!) –

+0

penso che questa soluzione abbia un sovraccarico non necessario;) –

+0

@Brandon grazie, corretto – helloandre

4

Risposta semplice: non utilizzare un ciclo foreach. Utilizzare un semplice for ciclo invece:

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

Questo non funziona per gli array associativi come dizionari e hashtables, giusto? –

+0

@Brandon Sì, corretto. – lonesomeday

1

si dovrebbe essere in grado di utilizzare:

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

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

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

Questo copia matrice e poi si sposta il puntatore lungo di 1.

1

La soluzione più semplice è IMO per cambiare la tua mentalità. Invece di controllare il record corrente e quello successivo, controlla il record precedente e quello corrente. Ricordare il precedente è più facile che ottenere il prossimo.

Se non si desidera che, è possibile anche fosso il foreach e iterare in stile C usando for e una variabile contatore - un CAVET però: array sparsi di PHP possono fare molto, in modo da meglio chiamata array_values() sulla matrice ispezionato prima di iterare.

1

Se si desidera lavorare con foreach, è possibile confrontare il valore corrente con il valore di precedente invece che con il valore successivo:

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

Con questo è sufficiente spostare l'intero iterazione un oggetto.

1

Perché non utilizzare un ciclo for normale piuttosto che l'iteratore 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

Questo non funziona per gli array associativi, come dizionari e tabelle hash, giusto? –

+0

@Brandon Dovresti estrarre gli array_keys e iterare usando quelli in quell'istanza. –

+0

@Brandon Incidentalmente, stavo solo delineando un potenziale percorso, questo (e in effetti tutti gli altri fino ad oggi) ovviamente non sono implementazioni utilizzabili mentre calpestano felicemente la "percentuale diff" ogni volta che iterano. :-) –

1

'di solito è più facile da utilizzare il valore precedente di quello successivo:

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

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

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

Il valore precedente avrebbe funzionato: in questo modo sarebbe molto più semplice in realtà ... non so perché non ci pensassi :) – 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; 
} 

ci sono infatti array iterator funzioni che supportano quello che ti serve, e anche semplicemente loop traverso una matrice con next()/prev() ecc funziona bene ma la soluzione sopra è più elegante

Non funziona con foreach perché foreach crea una copia dei riferimenti e non imposta i puntatori degli array in th e matrice stessa.

Ecco un esempio che può essere utilizzato per gli array associativi mediante funzioni matrice iterator_traits:

$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

Questo non funziona per gli array associativi come dizionari e hashtables, giusto? –

+0

è corretto, ecco perché ho collegato le funzioni di iteratore dell'array che sono perfettamente adatte. un'altra possibilità è ricordare l'ultimo elemento dell'array e calcolare in base a quello e spostare l'output di una voce - ho aggiunto un codice di esempio alla risposta –