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.

57
demandé sur ndmeiri 2014-01-23 12:42:21

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:]):
    ...
74
répondu sberry 2014-01-23 08:45:47

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)   
28
répondu Bach 2014-01-23 09:06:30

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
7
répondu thefourtheye 2014-01-23 08:51:16

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
0
répondu Noctua 2014-01-23 08:48:19

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)
-1
répondu Burak Cetin 2016-05-21 17:06:18