Цикл через список, начинающийся с определенного элемента
Скажем, у меня есть список:
l = [1, 2, 3, 4]
И я хочу пройти через него. Обычно это будет делать что-то вроде этого,
1, 2, 3, 4, 1, 2, 3, 4, 1, 2...
Я хочу, чтобы начать с определенной точки цикла, не обязательно с индексом, но, возможно, с соответствующим элементом. Скажем, я хотел начать с любого элемента в списке ==4
, тогда выход был бы,
4, 1, 2, 3, 4, 1, 2, 3, 4, 1...
Как я могу это сделать?
Ответы
Ответ 1
Посмотрите itertools модуль. Он предоставляет все необходимые функции.
from itertools import cycle, islice, dropwhile
L = [1, 2, 3, 4]
cycled = cycle(L) # cycle thorugh the list 'L'
skipped = dropwhile(lambda x: x != 4, cycled) # drop the values until x==4
sliced = islice(skipped, None, 10) # take the first 10 values
result = list(sliced) # create a list from iterator
print(result)
Вывод:
[4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
Ответ 2
Используйте арифметический оператор mod
. Предположим, что вы начинаете с позиции k
, тогда k
следует обновить следующим образом:
k = (k + 1) % len(l)
Если вы хотите начать с определенного элемента, а не индекса, вы всегда можете найти его как k = l.index(x)
, где x - желаемый элемент.
Ответ 3
Я не такой большой поклонник импорта модулей, когда вы можете делать что-то своими силами в нескольких строках. Здесь мое решение без импорта:
def cycle(my_list, start_at=None):
start_at = 0 if start_at is None else my_list.index(start_at)
while True:
yield my_list[start_at]
start_at = (start_at + 1) % len(my_list)
Это вернет (бесконечный) итератор, зацикливающий ваш список. Чтобы получить следующий элемент цикла, вы должны использовать оператор next
:
>>> it1 = cycle([101,102,103,104])
>>> next(it1), next(it1), next(it1), next(it1), next(it1)
(101, 102, 103, 104, 101) # and so on ...
>>> it1 = cycle([101,102,103,104], start_at=103)
>>> next(it1), next(it1), next(it1), next(it1), next(it1)
(103, 104, 101, 102, 103) # and so on ...
Ответ 4
import itertools as it
l = [1, 2, 3, 4]
list(it.islice(it.dropwhile(lambda x: x != 4, it.cycle(l)), 10))
# returns: [4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
поэтому желаемый итератор:
it.dropwhile(lambda x: x != 4, it.cycle(l))
Ответ 5
Hm, http://docs.python.org/library/itertools.html#itertools.cycle не имеет такого начального элемента.
Может быть, вы все равно начинаете цикл и бросаете первые элементы, которые вам не нравятся.
Ответ 6
Другим странным вариантом является то, что циклическое перемещение по спискам может быть выполнено заново. Например:
# Run this once
myList = ['foo', 'bar', 'baz', 'boom']
myItem = 'baz'
# Run this repeatedly to cycle through the list
if myItem in myList:
myItem = myList[myList.index(myItem)-1]
print myItem
Ответ 7
Можно использовать что-то вроде этого:
def my_cycle(data, start=None):
k = 0 if not start else start
while True:
yield data[k]
k = (k + 1) % len(data)
Затем запустите:
for val in my_cycle([0,1,2,3], 2):
print(val)
По сути то же самое, что и один из предыдущих ответов. Виноват.