Получение следующего элемента при циклическом повторении через список

li = [0, 1, 2, 3]

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

Когда это достигает последнего элемента, IndexError повышен (как имеет место для любого списка, кортежа, словаря, или представьте в виде строки, который выполнен с помощью итераций). Я на самом деле хочу в той точке для nextelem равняться li[0]. Мое довольно громоздкое решение этого было

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

Существует ли лучший способ сделать это?

42
задан igaurav 15 October 2014 в 12:03
поделиться

4 ответа

После тщательного обдумывания я думаю, что это лучший способ. Он позволяет легко выйти посередине, не используя перерыв, что я считаю важным, и требует минимальных вычислений, так что я думаю, что это самый быстрый способ. Также не требуется, чтобы li был списком или кортежом. Это может быть любой итератор.

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)

Я оставляю другие решения здесь для потомков.

Все эти причудливые итераторы имеют свое место, но не здесь. Используй оператор %.

li = [0, 1, 2, 3]

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

Теперь, если вы собираетесь бесконечно перебирать список, то просто сделайте так:

li = [0, 1, 2, 3]

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

Я думаю, что это проще понять, чем другое решение, включающее тройку , и, возможно, тоже быстрее. Если вы уверены, что список не изменит размера, вы можете пропустить копию len(li) и использовать ее.

Это также позволит вам легко сойти с колеса обозрения в середине, вместо того, чтобы ждать, пока ведро снова опустится на дно. В других решениях (в том числе и в Вашем) необходимо проверить работающую в середине петли на наличие , а затем ломать .

78
ответ дан 26 November 2019 в 23:29
поделиться
while running:
    for elem,next_elem in zip(li, li[1:]+[li[0]]):
        ...
15
ответ дан 26 November 2019 в 23:29
поделиться

Можно использовать парный циклический итератор:

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
ответ дан 26 November 2019 в 23:29
поделиться
while running:
    lenli = len(li)
    for i, elem in enumerate(li):
        thiselem = elem
        nextelem = li[(i+1)%lenli]
3
ответ дан 26 November 2019 в 23:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: