Les solutions jusqu'à présent ne concernent que les listes, et la plupart copient la liste. D'après mon expérience, ce n'est souvent pas possible.
En outre, ils ne traitent pas du fait que vous pouvez avoir des éléments répétés dans la liste.
Le titre de votre question dit " Valeurs précédentes et suivantes dans une boucle ", mais si vous exécutez la plupart des réponses ici dans une boucle, vous finirez par parcourir à nouveau la liste entière sur chaque élément pour le trouver.
Donc je viens de créer une fonction qui. en utilisant le itertools
module, divise et tranche l'itérable, et génère des tuples avec les éléments précédent et suivant ensemble. Ce n'est pas exactement ce que fait votre code, mais cela vaut la peine d'y jeter un coup d'œil, car il peut probablement résoudre votre problème.
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
Ensuite, utilisez-le dans une boucle, et vous aurez les éléments précédents et suivants:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
Les resultats:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
Cela fonctionnera avec n'importe quelle liste de taille (car il ne copie pas la liste), et avec n'importe quel itérable (fichiers, ensembles, etc.). De cette façon, vous pouvez simplement parcourir la séquence et avoir les éléments précédents et suivants disponibles dans la boucle. Pas besoin de rechercher à nouveau l'élément dans la séquence.
Une brève explication du code:
tee
est utilisé pour créer efficacement 3 itérateurs indépendants sur la séquence d'entrée
chain
relie deux séquences en une seule; il est utilisé ici pour ajouter une séquence à un seul élément[None]
à àprevs
islice
est utilisé pour faire une séquence de tous les éléments sauf le premier, puis chain
est utilisé pour ajouter unNone
à sa fin
- Il y a maintenant 3 séquences indépendantes basées sur
some_iterable
qui ressemblent à:
prevs
: None, A, B, C, D, E
items
: A, B, C, D, E
nexts
: B, C, D, E, None
- enfin
izip
est utilisé pour changer 3 séquences en une séquence de triplets.
Notez que izip
s'arrête quand une séquence d'entrée est épuisée, donc le dernier élément de prevs
sera ignoré, ce qui est correct - il n'y a pas d'élément tel que le dernier élément serait le sien prev
. Nous pourrions essayer de supprimer les derniers éléments de prevs
maisizip
le comportement de ce dernier rend cela redondant
Notez également que tee
, izip
, islice
etchain
venir du itertools
module; ils opèrent sur leurs séquences d'entrée à la volée (paresseusement), ce qui les rend efficaces et n'introduit pas le besoin d'avoir toute la séquence en mémoire à la fois à tout moment.
Dans python 3
, il affichera une erreur lors de l'importation izip
, vous pouvez utiliser à la zip
place de izip
. Pas besoin d'importer zip
, il est prédéfini dans python 3
- source