Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Продумав это тщательно, я думаю, что это лучший способ. Он позволяет легко отступать в середине без использования break, который, как мне кажется, важен, и требует минимальных вычислений, поэтому я считаю это самым быстрым. Также не требуется, чтобы 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]

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

Это также позволяет легко отходить от колеса ферриуса посередине вместо того, чтобы ждать, пока ковш снова опустится вниз. Другие решения (включая ваши) требуют проверки running в середине цикла for, а затем break.

Ответ 2

while running:
    for elem,next_elem in zip(li, li[1:]+[li[0]]):
        ...

Ответ 3

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

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)):
    ...

Ответ 4

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

Ответ 5

Использовать zip-метод в Python. Эта функция возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждой последовательности аргументов или итераций

    while running:
        for thiselem,nextelem in zip(li, li[1 : ] + li[ : 1]):
            #Do whatever you want with thiselem and nextelem         

Ответ 6

Совсем другой способ решить эту проблему:

   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]

Ответ 7

        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)]

Ответ 8

c = [ 1, 2, 3, 4 ]

i = int(raw_input(">"))

if i < 4:
    print i + 1
else:
    print -1