J'ai parfois besoin d'itérer une liste en Python en regardant l'élément "courant" et l'élément "suivant". Jusqu'à présent, je l'ai fait avec du code comme:
for current, next in zip(the_list, the_list[1:]):
# Do something
Cela fonctionne et fait ce que j'attends, mais y a-t-il un moyen plus idiomatique ou plus efficace de faire la même chose?
next
cette façon masque un fichier intégré.next
est également une fonction intégrée dans Python 2.Réponses:
Voici un exemple pertinent tiré de la documentation du module itertools :
Pour Python 2, vous avez besoin
itertools.izip
au lieu dezip
:Comment ça marche:
Tout d' abord, deux itérateurs parallèles,
a
etb
sont créés (l'tee()
appel), les deux pointant vers le premier élément de la iterable originale. Le deuxième itérateur,b
est déplacé d'un pas en avant (l'next(b, None)
appel). À ce stade,a
pointe vers s0 etb
pointe vers s1. Les deuxa
etb
peuvent parcourir l'itérateur d'origine indépendamment - la fonction izip prend les deux itérateurs et crée des paires d'éléments retournés, en faisant avancer les deux itérateurs au même rythme.Une mise en garde: la
tee()
fonction produit deux itérateurs qui peuvent avancer indépendamment l'un de l'autre, mais cela a un coût. Si l'un des itérateurs avance plus loin que l'autre, alorstee()
doit conserver les éléments consommés en mémoire jusqu'à ce que le deuxième itérateur les reprenne également (il ne peut pas «rembobiner» l'itérateur d'origine). Ici, cela n'a pas d'importance car un itérateur n'a qu'une longueur d'avance sur l'autre, mais en général, il est facile d'utiliser beaucoup de mémoire de cette façon.Et comme
tee()
peut prendre unn
paramètre, cela peut également être utilisé pour plus de deux itérateurs parallèles:la source
zip(ł, ł[1:])
est beaucoup plus court et pythoniquefuncy
module:funcy.pairwise
: funcy.readthedocs.io/en/stable/seqs.html#pairwiseRoulez le vôtre!
la source
Puisque
the_list[1:]
crée en fait une copie de la liste entière (à l'exclusion de son premier élément), etzip()
crée une liste de tuples immédiatement lorsqu'elle est appelée, au total trois copies de votre liste sont créées. Si votre liste est très longue, vous préférerez peut-êtrequi ne copie pas du tout la liste.
la source
the_list[1:]
seulement un objet de tranche plutôt qu'une copie de presque toute la liste - la technique de l'OP n'est donc pas aussi inutile que vous la faites paraître.[1:]
crée l'objet slice (ou éventuellement "1:
"), qui est passé__slice__
dans la liste, qui retourne ensuite une copie contenant uniquement les éléments sélectionnés. Une façon idiomatique de copier une liste estl_copy = l[:]
(que je trouve moche et illisible - je préfèrel_copy = list(l)
)__slice__
méthode spéciale.the_list[1:]
est équivalent àthe_list[slice(1, None)]
, qui à son tour équivaut àlist.__getitem__(the_list, slice(1, None))
.the_list[1:]
n'est qu'une copie superficielle, elle se compose donc d'un seul pointeur par élément de liste. La partie la plus gourmande en mémoire estzip()
elle - même, car elle créera une liste d'unetuple
instance par élément de liste, chacune contenant deux pointeurs vers les deux éléments et des informations supplémentaires. Cette liste consommera neuf fois la quantité de mémoire consommée par la copie[1:]
.Je suis juste en train de sortir ça, je suis très surpris que personne n'ait pensé à enumerate ().
la source
if
peut également être supprimé si vous utilisez le tranchage:for (index, thing) in enumerate(the_list[:-1]): current, next_ = thing, the_list[index + 1]
Itérer par index peut faire la même chose:
Production:
la source
i
soit toujours l'index de l'élément courant.Ceci est maintenant une simple importation à partir du 16 mai 2020
Docs pour plus-itertools Sous le capot, ce code est le même que celui des autres réponses, mais je préfère de les importations lorsqu'elles sont disponibles.
Si vous ne l'avez pas déjà installé, alors:
pip install more-itertools
Exemple
Par exemple, si vous aviez la séquence fibbonnacci, vous pourriez calculer les ratios des paires suivantes comme suit:
la source
Paires d'une liste en utilisant une compréhension de liste
Production:
la source
Je suis vraiment surpris que personne n'ait mentionné la solution la plus courte, la plus simple et surtout générale :
Python 3:
Python 2:
Cela fonctionne pour une itération par paire en passant
n=2
, mais peut gérer tout nombre supérieur:la source
Une solution basique:
la source
la source