2017-01-31 6 views
0

У меня есть список, и я ищу для этого цикл. Беда в том, что меня не интересует циклическое перемещение по элементам по одному, но я хочу циклически перемещаться по элементам n за раз.`Itertools.cycle`: самый pythonic способ сделать несколько шагов?

Например, если мой список l = ["a", "b", "c", "d"], то я хотел бы следующий вывод:

>>> from itertools import cycle 
>>> gen = cycle(l) 
>>> next(gen, 4) # I know this doesn't work -- take as pseudocode 
d 
>>> next(gen, 3) 
c 

Я знаю, что я могу сделать это с чем-то вроде:

def generator_step(g, n): 
    for item in range(n): 
     next(g) 
    return item 
+0

Это должно быть 4 шага? Это не 4 шага во втором вызове. – user2357112

+0

@ user2357112 исправлено, извините – Newb

+1

Возможно, вы захотите просто сохранить список и индекс для прыжков в реальном времени. Вы не можете получить это с помощью итератора 'itertools.cycle'. ('collections.deque' и его метод' rotate' также заслуживают рассмотрения, но это не постоянное время.) – user2357112

ответ

1

Вы можете использовать itertools.islice для продвижения объекта цикла до следующего вызова:

from itertools import cycle, islice 

c = cycle(l) 
n = 4 
print(next(islice(c, n-1, n))) 
# d 
+0

Почему ваша функция 'islice' принимает три аргумента? Я считаю вывод с 'islice (c, n)' удовлетворительным. – Newb

+0

Это дает только первый элемент в срезе, когда вы вызываете 'next', что не то, что вы хотите –

1

В документации для itertools есть handy recipe for precisely this problem.

def consume(iterator, n): 
    "Advance the iterator n-steps ahead. If n is none, consume entirely." 
    # Use functions that consume iterators at C speed. 
    if n is None: 
     # feed the entire iterator into a zero-length deque 
     collections.deque(iterator, maxlen=0) 
    else: 
     # advance to the empty slice starting at position n 
     next(islice(iterator, n, n), None)