web-dev-qa-db-fra.com

Obtenir le prochain élément en parcourant une liste

li = [0, 1, 2, 3]

running = True
while running:
    for elem in li:
        thiselem = elem
        nextelem = li[li.index(elem)+1]

Lorsque ceci atteint le dernier élément, une IndexError est déclenchée (comme c'est le cas pour toute liste, tuple, dictionnaire ou chaîne itéré). À ce stade, je souhaite que nextelem soit égal à li[0]. Ma solution plutôt lourde à cela était

while running:
    for elem in li:
        thiselem = elem
        nextelem = li[li.index(elem)-len(li)+1]   # negative index

Existe-t-il une meilleure façon de le faire?

35
ignoramus

Après avoir bien réfléchi à cette question, je pense que c'est la meilleure solution. Il vous permet de vous déplacer facilement au milieu sans utiliser break, ce qui me semble important, et nécessite un minimum de calcul, donc je pense que c'est le plus rapide. De plus, il n'est pas nécessaire que li soit une liste ou un tuple. Ce pourrait être n'importe quel itérateur.

from itertools import cycle

li = [0, 1, 2, 3]

running = True
licycle = cycle(li)
# Prime the pump
nextelem = next(licycle)
while running:
    thiselem, nextelem = nextelem, next(licycle)

Je laisse les autres solutions ici pour la postérité.

Tous ces trucs fantaisie d'itérateur ont leur place, mais pas ici. Utilisez l'opérateur%.

li = [0, 1, 2, 3]

running = True
while running:
    for idx, elem in enumerate(li):
        thiselem = elem
        nextelem = li[(idx + 1) % len(li)]

Maintenant, si vous avez l’intention de parcourir une liste à l’infini, procédez comme suit:

li = [0, 1, 2, 3]

running = True
idx = 0
while running:
    thiselem = li[idx]
    idx = (idx + 1) % len(li)
    nextelem = li[idx]

Je pense que c'est plus facile à comprendre que l'autre solution impliquant tee, et probablement plus rapide aussi. Si vous êtes sûr que la liste ne changera pas de taille, vous pouvez récupérer une copie de len(li) et l'utiliser.

Cela vous permet également de descendre facilement de la grande roue au milieu au lieu d'attendre que le seau redescende. Les autres solutions (y compris la vôtre) nécessitent que vous vérifiiez running au milieu de la boucle for, puis break.

66
Omnifarious
while running:
    for elem,next_elem in Zip(li, li[1:]+[li[0]]):
        ...
12
John La Rooy

Vous pouvez utiliser un itérateur cyclique par paires:

from itertools import izip, cycle, tee

def pairwise(seq):
    a, b = tee(seq)
    next(b)
    return izip(a, b)

for elem, next_elem in pairwise(cycle(li)):
    ...
7
Ants Aasma

Utilisez la méthode Zip en Python. Cette fonction retourne une liste de n-uplets, où le i-ème tuple contient le i-ème élément de chacune des séquences d'arguments ou iterables.

    while running:
        for thiselem,nextelem in Zip(li, li[1 : ] + li[ : 1]):
            #Do whatever you want with thiselem and nextelem         
5
Nirmal
while running:
    lenli = len(li)
    for i, elem in enumerate(li):
        thiselem = elem
        nextelem = li[(i+1)%lenli]
3
Ned Batchelder

Une façon assez différente de résoudre ceci: 

   li = [0,1,2,3]

   for i in range(len(li)):

       if i < len(li)-1:

           # until end is reached
           print 'this', li[i]
           print 'next', li[i+1]

       else:

           # end
           print 'this', li[i]
3
Timothy Dalton
        li = [0, 1, 2, 3]
        for elem in li:
            if (li.index(elem))+1 != len(li):
                thiselem = elem
                nextelem = li[li.index(elem)+1]
                print 'thiselem',thiselem
                print 'nextel',nextelem
            else:
                print 'thiselem',li[li.index(elem)]
                print 'nextel',li[li.index(elem)]
0
Satheesh Alathiyur