如何指定itertools.cycle函数的起始位置

时间:2017-02-25 17:56:16

标签: python python-3.x itertools

我需要循环浏览1-4之间的起始位置列表 使用itertools我可以在列表中循环

positions = itertools.cycle([1,2,3,4])
next(positions)

这确实会返回下一个位置,但下次我需要从3开始怎么办?如何设置起始位置?

我需要经常更改开始位置,我不能将列表更改为从3开始。

4 个答案:

答案 0 :(得分:7)

您无法设置起始位置;它总是从给定序列开始的地方开始。

可以将循环移动几步,然后再根据需要使用它。使用itertools.islice()跳过一些项目:

from itertools import islice

starting_at_three = islice(positions, 2, None)

你传递了iterable,然后是一个开始和结束值; None这里意味着islice()迭代器将永远持续或直到底层positions迭代器耗尽。

演示:

>>> from itertools import islice, cycle
>>> positions = cycle([1, 2, 3, 4])
>>> starting_at_three = islice(positions, 2, None)
>>> next(starting_at_three)
3
>>> next(starting_at_three)
4
>>> next(starting_at_three)
1

另一种选择是传递不同的顺序;例如,你可以传递[3, 4, 1, 2]

答案 1 :(得分:1)

您可以使用itertools.islice

from itertools import cycle
from itertools import islice

positions3 = islice(cycle([1,2,3,4]),2,None)

这将导致发射器发出3,4,1,2,3,4,1,2,3,4,...

如果起始位置k很大(与原始列表的长度相比),则可以先付款以执行模数:

from itertools import cycle
from itertools import islice

source_list = [1,2,3,4]
k = 10000000 # offset index
positions_k = islice(cycle(source_list),k%len(source_list),None)

这将生成等效结果,但islice不会删除前10M元素。

答案 2 :(得分:0)

使用原始列表的切片:

In [15]: def custom_slice(lst, start):
   ....:     return cycle(lst[start:] + lst[:start + 1])

演示:

In [16]: positions = custom_slice(lst, 2)

In [17]: next(positions)
Out[17]: 3

In [18]: next(positions)
Out[18]: 4

In [19]: next(positions)
Out[19]: 1

In [20]: next(positions)
Out[20]: 2

答案 3 :(得分:0)

您可以使用 itertools.dropwhile 执行此操作。它将忽略值,直到满足谓词函数为止,然后在整个循环中继续迭代。

>>> c = itertools.cycle([1, 2, 3, 4, 5])
>>> dw = itertools.dropwhile(lambda x: x < 3, c)
>>> [next(dw) for _ in range(10)]
[3, 4, 5, 1, 2, 3, 4, 5, 1, 2]

但是,如文档中所述

<块引用>

迭代器在谓词第一次变为假之前不会产生任何输出,因此它的启动时间可能很长

所以最好在这个用例中使用 islice

>>> timeit.timeit(setup='from itertools import cycle, islice', 
      stmt='c = cycle(range(1000)); sl = islice(c, 900, None); assert next(sl) == 900')
35.37439359538257

>>> timeit.timeit(setup='from itertools import cycle, dropwhile', 
      stmt='c = cycle(range(1000)); dw = dropwhile(lambda x: x < 900, c); assert next(dw) == 900')
131.17783254291862