Получение следующего элемента при циклическом перемещении по списку
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
Есть ли лучший способ сделать это?
Ответы
Ответ 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