Jusqu'à présent, les solutions ne concernent que les listes, et la plupart d'entre elles copient la liste. D'après mon expérience, ce n'est souvent pas possible.
En outre, elles ne tiennent pas compte du fait que la liste peut contenir des éléments répétés.
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 à l'intérieur d'une boucle, vous finirez par itérer sur la liste entière à nouveau sur chaque élément pour le trouver.
Donc, je viens de créer une fonction qui. en utilisant la itertools
divise et découpe l'itérable, et génère des tuples avec les éléments précédents et suivants ensemble. Ce n'est pas exactement ce que fait votre code, mais cela vaut la peine d'y jeter un coup d'œil, car cela 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)
Utilisez-le ensuite dans une boucle, et vous aurez des é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 résultats :
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
Il fonctionnera avec une liste de n'importe quelle taille (parce qu'il ne copie pas la liste), et avec n'importe quel itérable (fichiers, ensembles, etc). De cette façon, vous pouvez simplement itérer sur la séquence, et avoir les éléments précédents et suivants disponibles dans la boucle. Il n'est pas nécessaire 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]
a prevs
-
islice
est utilisé pour faire une séquence de tous les éléments sauf le premier, alors chain
est utilisé pour ajouter un None
jusqu'à son terme
- 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 transformer 3 séquences en une séquence de triplets.
Notez que izip
s'arrête lorsque toute 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 de tel élément que le dernier élément serait son prev
. Nous pourrions essayer de retirer les derniers éléments de prevs
mais izip
Le comportement de l'entreprise rend cela superflu
Notez également que tee
, izip
, islice
y chain
proviennent de la itertools
Ils opèrent sur leurs séquences d'entrée à la volée (paresseusement), ce qui les rend efficaces et n'introduit pas la nécessité d'avoir la séquence entière en mémoire à tout moment.
Sur python 3
il y aura une erreur lors de l'importation izip
,vous pouvez utiliser zip
au lieu de izip
. Il n'est pas nécessaire d'importer zip
il est prédéfini dans python 3
- fuente