web-dev-qa-db-fra.com

Itérer sur toutes les paires d'éléments consécutifs d'une liste

À partir d'une liste

l = [1, 7, 3, 5]

Je souhaite parcourir toutes les paires d'éléments de liste consécutifs (1,7), (7,3), (3,5), c.-à-d.

for i in xrange(len(l) - 1):
    x = l[i]
    y = l[i + 1]
    # do something

Je voudrais faire cela d'une manière plus compacte, comme

for x, y in someiterator(l): ...

Y a-t-il un moyen de faire cela en utilisant les itérateurs Python intégrés? Je suis sûr que le module itertools devrait avoir une solution, mais je ne peux pas le comprendre.

60
flonk

Il 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 pour lesquelles vous ne souhaitez pas créer de nouvelle liste.

import itertools

for first, second in itertools.izip(l, l[1:]):
    ...
88
sberry

Regardez pairwise dans les recettes d’itertools: 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 n-uplets de toute taille naturelle positive, 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)   
28
Bach

Je créerais un générateur générique grouper, comme celui-ci

def grouper(input_list, n = 2):
    for i in xrange(len(input_list) - (n - 1)):
        yield input_list[i:i+n]

Exemple de cycle 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 de cycle 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
7
thefourtheye

Vous pouvez utiliser une Zip.

>>> list(Zip(range(5), range(2, 6)))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]

Tout comme une fermeture à glissière, il 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ération va comme

for x, y in Zip(l[:-1], l[1:]):
    pass
0
Noctua

Généraliser l'approche de sberry à nwise avec compréhension:

def nwise(lst, k=2):
    return list(Zip(*[lst[i:] for i in range(k)])) 

Par exemple

nwise(list(range(10)),3)

[(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7 ), (6, 7, 8), (7, 8, 9)]

0
alancalvitti