问题描述
我想通过 2 个不同的 itertools.count
屈服。我把两者结合起来
使用 itertools.chain.from_iterable
这是我为它编写的代码。
return itertools.chain.from_iterable([itertools.count(start=2,step=2),itertools.count(start=7,step=7)])
问题是它试图在处理下一个计数器(第 7 步)之前完成第一个计数器(第 2 步)
2
4
6
8
10
...
但我想交替骑车。
预期输出:
2 # 2*1
7 # 7*1
4 # 2*2
14 # 7*2
6 # 2*3
21 # 7*3
8 # 2*4
28 # 7*4
以下是我迄今为止尝试过的其他方法:
yield from [elem for elem in [next(count(start=2,step=2)),next(count(start=7,step=7))]]
上述循环交替进行,但每次产量后计数器都会重置。
2
7
2
7
2
7
我希望这完全在 itertools
或列表理解上实现
因为它们是内存优化的,因此我希望该函数返回 generator object
。此外,如果解决方案在一行上会更好。
编辑:
正如 jonrsharpe 在评论中所建议的,我已经实现了 roundrobin
iter 技术,并且能够获取所需的输出。
from itertools import count,cycle
def pattern_generator():
return cycle(iter(it).__next__ for it in [
count(start=2,count(start=7,step=7),])
gen = pattern_generator()
print(next(gen)())
print(next(gen)())
print(next(gen)())
print(next(gen)())
我对这个输出很满意。但是,是否可以在不调用 iter 的 next 方法的情况下调用 next
?即,在 ()
中不使用 next(gen)()
?
提前致谢。
解决方法
您可以通过多种方式制作发电机
内联
#for i in (i for t in zip('abc',range(3)) for i in t):
#EDIT: more readable solution
for i in itertools.chain.from_iterable(zip('abc',range(3))):
print(i)
编辑 2:解释zip
连接每个可迭代对象的第 n 个(返回 tuple
的 ('a',0),('b',1) ...
序列)
所以这大致转化为 itertools.chain.from_iterable([('a',1),...])
调用 chain.from_iterable
类似于调用 chain
所以现在我们有chain(('a',('c',2))
由于 tuple
是可迭代的,chain
遍历 ('a',0)
,然后 ('b',1)
等等from_iterable
和 zip
都是需要的,因为它们实际上都没有创建列表 [('a',...]
(在您的情况下是无限的)
功能一
def alternate(*iterables):
for t in zip(*iterables):
yield from t # or for i in t: yield i
功能 2
def alternate(*iterables):
iterables = [iter(it) for it in iterables]
while True:
try:
for it in iterables:
yield next(it)
except StopIteration:
break
结果
for i in alternate('abc',range(3)):
print(i)
a
0
b
1
c
2
函数方法也提供了更大的灵活性