Obtenir l'élément suivant dans la boucle de foreach

j'ai une boucle foreach et je veux voir s'il y a un élément suivant dans la boucle pour que je puisse comparer l'élément courant avec le suivant. Comment puis-je faire cela? J'ai lu sur les fonctions actuelles et à venir, mais je ne sais pas comment les utiliser.

Merci d'avance

39
demandé sur chchrist 2011-02-23 23:38:39

9 réponses

une approche unique serait d'inverser le tableau et boucle. Cela fonctionnera également pour les tableaux non indexés numériquement:

$items = array(
    'one'   => 'two',
    'two'   => 'two',
    'three' => 'three'
);
$backwards = array_reverse($items);
$last_item = NULL;

foreach ($backwards as $current_item) {
    if ($last_item === $current_item) {
        // they match
    }
    $last_item = $current_item;
}

si vous êtes toujours intéressé à utiliser le current et next fonctions, vous pourriez faire ceci:

$items = array('two', 'two', 'three');
$length = count($items);
for($i = 0; $i < $length - 1; ++$i) {
    if (current($items) === next($items)) {
        // they match
    }
}

#2 est probablement la meilleure solution. Remarque, $i < $length - 1; arrêt de la boucle après avoir comparé les deux derniers éléments du tableau. J'ai mis cela dans la boucle pour être explicite avec l'exemple. Tu devrais probablement juste calculer $length = count($items) - 1;

27
répondu Stephen 2011-02-23 21:03:58

php.net/foreach:

à moins que le tableau ne soit référencé, foreach opère sur une copie du tableau spécifié et non sur le tableau lui-même. foreach a quelques effets secondaires sur le pointeur tableau. Ne vous fiez pas au pointeur du tableau pendant ou après l'attaque sans le réinitialiser.

En d'autres termes, ce n'est pas une très bonne idée de faire ce que vous demandez de faire. Peut-être que ce serait une bonne idée de parler à quelqu'un de pourquoi vous êtes essayer de faire ça, voir si il y a une meilleure solution? N'hésitez pas à nous demander en # # PHP sur irc.freenode.net si vous n'avez pas d'autres ressources disponibles.

9
répondu TML 2011-02-24 08:05:28

Vous pouvez probablement utiliser while loop au lieu de foreach:

while ($current = current($array) )
{
    $next = next($array);
    if (false !== $next && $next == $current)
    {
        //do something with $current
    }
}
9
répondu pronskiy 2013-04-12 07:27:19

Si les index sont continues:

foreach ($arr as $key => $val) {
   if (isset($arr[$key+1])) {
      echo $arr[$key+1]; // next element
   } else {
     // end of array reached
   }
}
6
répondu Mārtiņš Briedis 2018-08-06 01:06:49

si sa indexé numériquement:

foreach ($foo as $key=>$var){

    if($var==$foo[$key+1]){
        echo 'current and next var are the same';
    }
}
4
répondu Rob 2012-08-14 20:39:00

Vous pourriez obtenir les clés du tableau avant le foreach, puis utiliser un compteur pour vérifier l'élément suivant, quelque chose comme:

//$arr is the array you wish to cycle through
$keys = array_keys($arr);
$num_keys = count($keys);
$i = 1;
foreach ($arr as $a)
{
    if ($i < $num_keys && $arr[$keys[$i]] == $a)
    {
        // we have a match
    }
    $i++;
}

Cela fonctionne pour les deux tableaux simples, tels que array(1,2,3), et des tableaux à touches tels que array('first'=>1, 'second'=>2, 'thrid'=>3).

2
répondu eclipse31 2011-02-24 09:36:18

la solution générale pourrait être un itérateur de cache. Un itérateur de mise en cache correctement mis en œuvre fonctionne avec n'importe quel itérateur, et sauve de la mémoire. PHP SPL a un CachingIterator, mais il est très étrange, et a une fonctionnalité très limitée. Cependant, vous pouvez écrire votre propre anticipation itérateur comme ceci:

<?php

class NeighborIterator implements Iterator
{

    protected $oInnerIterator;

    protected $hasPrevious = false;
    protected $previous = null;
    protected $previousKey = null;

    protected $hasCurrent = false;
    protected $current = null;
    protected $currentKey = null;

    protected $hasNext = false;
    protected $next = null;
    protected $nextKey = null;

    public function __construct(Iterator $oInnerIterator)
    {
        $this->oInnerIterator = $oInnerIterator;
    }

    public function current()
    {
        return $this->current;
    }

    public function key()
    {
        return $this->currentKey;
    }

    public function next()
    {
        if ($this->hasCurrent) {
            $this->hasPrevious = true;
            $this->previous = $this->current;
            $this->previousKey = $this->currentKey;
            $this->hasCurrent = $this->hasNext;
            $this->current = $this->next;
            $this->currentKey = $this->nextKey;
            if ($this->hasNext) {
                $this->oInnerIterator->next();
                $this->hasNext = $this->oInnerIterator->valid();
                if ($this->hasNext) {
                    $this->next = $this->oInnerIterator->current();
                    $this->nextKey = $this->oInnerIterator->key();
                } else {
                    $this->next = null;
                    $this->nextKey = null;
                }
            }
        }
    }

    public function rewind()
    {
        $this->hasPrevious = false;
        $this->previous = null;
        $this->previousKey = null;
        $this->oInnerIterator->rewind();
        $this->hasCurrent = $this->oInnerIterator->valid();
        if ($this->hasCurrent) {
            $this->current = $this->oInnerIterator->current();
            $this->currentKey = $this->oInnerIterator->key();
            $this->oInnerIterator->next();
            $this->hasNext = $this->oInnerIterator->valid();
            if ($this->hasNext) {
                $this->next = $this->oInnerIterator->current();
                $this->nextKey = $this->oInnerIterator->key();
            } else {
                $this->next = null;
                $this->nextKey = null;
            }
        } else {
            $this->current = null;
            $this->currentKey = null;
            $this->hasNext = false;
            $this->next = null;
            $this->nextKey = null;
        }
    }

    public function valid()
    {
        return $this->hasCurrent;
    }

    public function hasNext()
    {
        return $this->hasNext;
    }

    public function getNext()
    {
        return $this->next;
    }

    public function getNextKey()
    {
        return $this->nextKey;
    }

    public function hasPrevious()
    {
        return $this->hasPrevious;
    }

    public function getPrevious()
    {
        return $this->previous;
    }

    public function getPreviousKey()
    {
        return $this->previousKey;
    }

}


header("Content-type: text/plain; charset=utf-8");
$arr = [
    "a" => "alma",
    "b" => "banan",
    "c" => "cseresznye",
    "d" => "dio",
    "e" => "eper",
];
$oNeighborIterator = new NeighborIterator(new ArrayIterator($arr));
foreach ($oNeighborIterator as $key => $value) {

    // you can get previous and next values:

    if (!$oNeighborIterator->hasPrevious()) {
        echo "{FIRST}\n";
    }
    echo $oNeighborIterator->getPreviousKey() . " => " . $oNeighborIterator->getPrevious() . " ----->        ";
    echo "[ " . $key . " => " . $value . " ]        -----> ";
    echo $oNeighborIterator->getNextKey() . " => " . $oNeighborIterator->getNext() . "\n";
    if (!$oNeighborIterator->hasNext()) {
        echo "{LAST}\n";
    }
}
2
répondu Dávid Horváth 2016-03-14 19:50:52

une boucle foreach en php va itérer sur une copie du tableau original, faisant next() et prev() fonctions inutiles. Si vous avez un tableau associatif et avez besoin de récupérer l'élément suivant, vous pouvez itérer sur les touches tableau à la place:

foreach (array_keys($items) as $index => $key) {
    // first, get current item
    $item = $items[$key];
    // now get next item in array
    $next = $items[array_keys($items)[$index + 1]];
}

Depuis le tableau de clés possède un indice continu lui-même, vous pouvez l'utiliser pour accéder au tableau d'origine.

Être conscient$next sera null pour la dernière itération, depuis il n'y a aucun élément suivant après le dernier. L'accès à des clés de tableau inexistantes lancera un avis php. Pour éviter cela, soit:

  1. Vérifiez la dernière itération avant d'attribuer des valeurs à $next
  2. vérifiez si la toucheindex + 1 existe array_key_exists()

en utilisant la méthode 2 l'avant-bras complet pourrait ressembler à ceci:

foreach (array_keys($items) as $index => $key) {
    // first, get current item
    $item = $items[$key];
    // now get next item in array
    $next = null;
    if (array_key_exists($index + 1, array_keys($items))) {
        $next = $items[array_keys($items)[$index + 1]];
    }
}
0
répondu Liquinaut 2016-02-14 16:39:24

vous pouvez obtenir les clés / valeurs et l'index

<?php
$a = array(
    'key1'=>'value1', 
    'key2'=>'value2', 
    'key3'=>'value3', 
    'key4'=>'value4', 
    'key5'=>'value5'
);

$keys = array_keys($a);
foreach(array_keys($keys) as $index ){       
    $current_key = current($keys); // or $current_key = $keys[$index];
    $current_value = $a[$current_key]; // or $current_value = $a[$keys[$index]];

    $next_key = next($keys); 
    $next_value = $a[$next_key] ?? null; // for php version >= 7.0

    echo  "{$index}: current = ({$current_key} => {$current_value}); next = ({$next_key} => {$next_value})\n";
}

résultat:

0: current = (key1 => value1); next = (key2 => value2) 
1: current = (key2 => value2); next = (key3 => value3) 
2: current = (key3 => value3); next = (key4 => value4) 
3: current = (key4 => value4); next = (key5 => value5) 
4: current = (key5 => value5); next = ( => )
0
répondu Andrei Krasutski 2018-03-23 15:17:12