Jetez un œil à l'avance lors de l'itération d'un tableau en PHP
Question
Est-il possible de « regarder en avant » lors de l'itération d'un tableau en PHP 5.2 ?Par exemple, j'utilise souvent foreach pour manipuler les données d'un tableau :
foreach($array as $object) {
// do something
}
Mais j'ai souvent besoin de jeter un coup d'œil à l'élément suivant en parcourant le tableau.Je sais que je pourrais utiliser un for
boucle et référence l'élément suivant par son index ($array[$i+1]
), mais cela ne fonctionnerait pas pour les tableaux associatifs.Existe-t-il une solution élégante à mon problème, impliquant peut-être SPL ?
La solution
Vous pouvez utiliser le CachingIterator à cet effet.
Voici un exemple:
$collection = new CachingIterator(
new ArrayIterator(
array('Cat', 'Dog', 'Elephant', 'Tiger', 'Shark')));
Le CachingIterator est toujours un pas derrière l'itérateur interne:
var_dump( $collection->current() ); // null
var_dump( $collection->getInnerIterator()->current() ); // Cat
Ainsi, quand vous foreach
sur $collection
, l'élément courant de la ArrayIterator intérieure sera l'élément suivant déjà, vous permettant de jeter un regard dans ce:
foreach($collection as $animal) {
echo "Current: $animal";
if($collection->hasNext()) {
echo " - Next:" . $collection->getInnerIterator()->current();
}
echo PHP_EOL;
}
Affichera:
Current: Cat - Next:Dog
Current: Dog - Next:Elephant
Current: Elephant - Next:Tiger
Current: Tiger - Next:Shark
Current: Shark
Pour une raison quelconque, je ne peux pas expliquer, le CachingIterator essayera toujours de convertir l'élément courant en chaîne. Si vous souhaitez effectuer une itération sur une collection d'objets et doivent propriétés accéder à une des méthodes, passer CachingIterator::TOSTRING_USE_CURRENT
comme deuxième au constructeur param.
Sur sidenote, le CachingIterator tire son nom de la capacité à mettre en cache tous les résultats qu'il a vus jusqu'à présent itératives. Pour que cela fonctionne, vous devez le instancier avec CachingIterator::FULL_CACHE
et vous pouvez chercher les résultats mises en cache getCache()
.
Autres conseils
Utilisez array_keys
.
$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
$cur = $array[$keys[$i]];
$next = $array[$keys[$i+1]];
}
Vous pouvez utiliser next
et prev
pour itérer un tableau. current
renvoie la valeur des articles en cours et key
la clé actuelle.
Alors vous pouvez faire quelque chose comme ceci:
while (key($array) !== null) {
next($array);
if (key($array) === null) {
// end of array
} else {
$nextItem = value($array);
}
prev($array);
// …
next($array);
}
Je sais que c'est un ancien poste, mais je peux expliquer cette chose en cours / suivant / prev mieux maintenant. Exemple:
$array = array(1,2,3,2,5);
foreach($array as $k => $v) {
// in foreach when looping the key() and current()
// is already pointing to the next record
// And now we can print current
print 'current key: '.$k.' and value: '.$v;
// if we have next we can print its information too (key+value)
if(current($array)) {
print ' - next key: '.key($array).' and value: '.current($array);
// at the end we must move pointer to next
next($array);
}
print '<br>';
}
// prints:
// current key: 0 and value: 1 - next key: 1 and value: 2
// current key: 1 and value: 2 - next key: 2 and value: 3
// current key: 2 and value: 3 - next key: 3 and value: 2
// current key: 3 and value: 2 - next key: 4 and value: 5
// current key: 4 and value: 5
Je sais que je pourrais utiliser une boucle for et référencer l'élément suivant par son index ($array[$i+1]), mais cela ne fonctionnerait pas pour les tableaux associatifs.
Pensez à convertir votre tableau associatif en un tableau indexé séquentiellement avec tableau_valeurs(), vous permettant d'utiliser la solution simple pour la boucle.