我需要循环浏览1-4
之间的起始位置列表
使用itertools
我可以在列表中循环
positions = itertools.cycle([1,2,3,4])
next(positions)
这确实会返回下一个位置,但下次我需要从3开始怎么办?如何设置起始位置?
我需要经常更改开始位置,我不能将列表更改为从3开始。
答案 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]
但是,如文档中所述
<块引用>迭代器在谓词第一次变为假之前不会产生任何输出,因此它的启动时间可能很长p>
所以最好在这个用例中使用 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