Itérer sur toutes les paires d'éléments consécutifs dans une liste
Étant donné une liste
l = [1, 7, 3, 5]
Je veux itérer sur toutes les paires d'éléments de liste consécutifs (1,7), (7,3), (3,5)
, c'est-à-dire
for i in xrange(len(l) - 1):
x = l[i]
y = l[i + 1]
# do something
Je voudrais le faire de façon plus compacte, comme
for x, y in someiterator(l): ...
Existe-t-il un moyen de le faire en utilisant des itérateurs Python intégrés? Je suis sûr que le module itertools
devrait avoir une solution, mais je n'arrive tout simplement pas à le comprendre.
5 réponses
Suffit d'utiliser zip
>>> l = [1, 7, 3, 5]
>>> for first, second in zip(l, l[1:]):
... print first, second
...
1 7
7 3
3 5
Comme suggéré, vous pouvez envisager d'utiliser la fonction izip
dans itertools
pour les très longues listes où vous ne voulez pas créer une nouvelle liste.
import itertools
for first, second in itertools.izip(l, l[1:]):
...
Regardez pairwise
à itertools recettes: http://docs.python.org/2/library/itertools.html#recipes
Citant à partir de là:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
Une Version Générale
Une version générale, qui donne des tuples de n'importe quelle taille naturelle positive donnée, peut ressembler à ceci:
def nwise(iterable, n=2):
iters = tee(iterable, n)
for i, it in enumerate(iters):
next(islice(it, i, i), None)
return izip(*iters)
Je créerais un générateur Générique grouper
, comme ceci
def grouper(input_list, n = 2):
for i in xrange(len(input_list) - (n - 1)):
yield input_list[i:i+n]
Exemple d'exécution 1
for first, second in grouper([1, 7, 3, 5, 6, 8], 2):
print first, second
Sortie
1 7
7 3
3 5
5 6
6 8
Exemple d'exécution 1
for first, second, third in grouper([1, 7, 3, 5, 6, 8], 3):
print first, second, third
Sortie
1 7 3
7 3 5
3 5 6
5 6 8
Vous pouvez utiliser un zip
.
>>> list(zip(range(5), range(2, 6)))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
Tout comme une fermeture à glissière, elle crée des paires. Donc, pour mélanger vos deux listes, vous obtenez:
>>> l = [1,7,3,5]
>>> list(zip(l[:-1], l[1:]))
[(1, 7), (7, 3), (3, 5)]
Puis itérer va comme
for x, y in zip(l[:-1], l[1:]):
pass
Ce qui est ci-dessous est très simple/lisible et fait ce travail, probablement aussi le plus efficace.
Convertir la liste en Générateur (ou mieux commencer par un itérateur à étoile avec):
gen = (x for x in l)
Convertissez-le en paires:
[(x, gen.next()) for x in gen]
C'est tout ce dont vous avez besoin.
Bien sûr, mieux vaut en faire un générateur aussi et lire à partir de ce que vous avez besoin:
( (x, gen.next()) for x in gen)