在Python中从无限生成器获取子集列表
摘要:我正在努力学习itertools.islice在Python中从无限生成器获取子集列表,python,generator,enumerate,Python,Generator,Enumerate,摘要:我正在努力学习itertools.islice 我试图找到一种最好的方法来获得一个列表,该列表由一个无限生成函数返回的子集组成。例如,我可能需要生成器中第1000到2000项的列表 这是我的示例生成器: def infinite_counter(): i = 0 while True: i += 2 yield i 这些值是我希望列表启动和停止的生成器的返回索引: start = 1000 end = 2000 方法1:列表理解(失败)
我试图找到一种最好的方法来获得一个列表,该列表由一个无限生成函数返回的子集组成。例如,我可能需要生成器中第1000到2000项的列表 这是我的示例生成器:
def infinite_counter():
i = 0
while True:
i += 2
yield i
这些值是我希望列表启动和停止的生成器的返回索引:
start = 1000
end = 2000
方法1:列表理解(失败)
这是可行的,但感觉真的像一个黑客。这也很难理解,但是我错误地认为它会比方法3快
方法3:简易方法(有效)
这是我第一次想到这样做,在我责怪自己不是蟒蛇之前。我感到惊讶的是,这在时间安排上几乎与方法2完全相同
方法4:itertools.takewhile(有效)
正如预期的那样,这比方法2和3慢得多
总的来说,我很惊讶地看到方法3的时间安排与方法2的时间安排非常接近。这是更多的代码,但更容易让人遵循。这就是我目前实现的方式
是否有其他的方法值得我考虑或更好的解决? 编辑:
方法6itertools.islice(获胜者) 这比具有列表理解功能的初始itertools.islice解决方案略快:[val for val in itertools.islice(infinite_counter(), start_ind, end_ind)]
令人惊讶的是找到正确的方法 对于那些记分的人,我的计时发现如下: 方法6=单位时间 方法2~=2.5*单位时间
from itertools import islice
list(islice(infinite_counter(), 1000, 2000))
方法3~=3*单位时间
from itertools import islice
list(islice(infinite_counter(), 1000, 2000))
方法4~=4.2*单位时间
from itertools import islice
list(islice(infinite_counter(), 1000, 2000))
方法5~=4*单位时间
from itertools import islice
list(islice(infinite_counter(), 1000, 2000))
请注意
list(next(iter([])) if ind > end else val for ind,val in enumerate(infinite_counter()) if ind >= start)
转换到这个
def _secret():
for ind, val in enumerate(infinite_counter()):
if ind >= start:
if ind > end:
yield list(next(iter([])))
else:
yield val
list(_secret())
这是很容易改进的
def _secret():
for ind, val in enumerate(infinite_counter()):
if ind < start:
continue
if ind > end:
break
yield val
list(_secret())
def_secret():
对于ind,枚举中的val(无穷多计数器()):
如果ind<开始:
持续
如果ind>结束:
打破
屈服值
列表(_secret())
这对我来说很好。找到正确的方法能做什么,真令人惊讶。谢谢无论你如何解决那些看起来很糟糕的事情,总能找到正确的解决方案。
from itertools import islice
list(islice(infinite_counter(), 1000, 2000))
list(next(iter([])) if ind > end else val for ind,val in enumerate(infinite_counter()) if ind >= start)
def _secret():
for ind, val in enumerate(infinite_counter()):
if ind >= start:
if ind > end:
yield list(next(iter([])))
else:
yield val
list(_secret())
def _secret():
for ind, val in enumerate(infinite_counter()):
if ind < start:
continue
if ind > end:
break
yield val
list(_secret())