循环嵌套生成器一次并重复
Cycle through nested generators once and repeat
我想通过 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
或列表理解来实现
因为它们是内存优化的,所以我希望函数 return a generator object
。另外,如果解决方案在一行上会更好。
编辑:
正如 jonrsharpe 在评论中所建议的那样,我已经实现了 roundrobin
iter 技术并且我能够获取所需的输出。
from itertools import count, cycle
def pattern_generator():
return cycle(iter(it).__next__ for it in [
count(start=2, step=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 个(returns 序列 tuple
s ('a', 0), ('b', 1) ...
)
所以这大致转化为 itertools.chain.from_iterable([('a', 0), ('b', 1), ...])
调用 chain.from_iterable
类似于调用 chain
所以现在我们有 chain(('a', 0), ('b', 1), ('c', 2))
因为 tuple
是可迭代的,所以 chain
遍历 ('a', 0)
,然后 ('b', 1)
等等
from_iterable
和 zip
都是必需的,因为两者都没有真正创建列表 [('a', 0), ('b', 1), ...]
(在你的情况下,它是无限的)
函数 1
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
函数方法也提供了更大的灵活性
我想通过 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
或列表理解来实现
因为它们是内存优化的,所以我希望函数 return a generator object
。另外,如果解决方案在一行上会更好。
编辑:
正如 jonrsharpe 在评论中所建议的那样,我已经实现了 roundrobin
iter 技术并且我能够获取所需的输出。
from itertools import count, cycle
def pattern_generator():
return cycle(iter(it).__next__ for it in [
count(start=2, step=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 个(returns 序列 tuple
s ('a', 0), ('b', 1) ...
)
所以这大致转化为 itertools.chain.from_iterable([('a', 0), ('b', 1), ...])
调用 chain.from_iterable
类似于调用 chain
所以现在我们有 chain(('a', 0), ('b', 1), ('c', 2))
因为 tuple
是可迭代的,所以 chain
遍历 ('a', 0)
,然后 ('b', 1)
等等
from_iterable
和 zip
都是必需的,因为两者都没有真正创建列表 [('a', 0), ('b', 1), ...]
(在你的情况下,它是无限的)
函数 1
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
函数方法也提供了更大的灵活性