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
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;
à 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.
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
}
}
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
}
}
si sa indexé numériquement:
foreach ($foo as $key=>$var){
if($var==$foo[$key+1]){
echo 'current and next var are the same';
}
}
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)
.
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";
}
}
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:
- Vérifiez la dernière itération avant d'attribuer des valeurs à
$next
- vérifiez si la touche
index + 1
existearray_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]];
}
}
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 = ( => )