我有一系列生成器:(gen_0,gen_1,... gen_n)
这些生成器将懒洋洋地创建它们的值但是有限并且可能具有不同的长度.
我需要能够构建另一个生成器,按顺序生成每个生成器的第一个元素,然后是第二个生成器,依此类推,从已经耗尽的生成器中跳过值.
我认为这个问题类似于取出元组
((1, 4, 7, 10, 13, 16), (2, 5, 8, 11, 14), (3, 6, 9, 12, 15, 17, 18))
Run Code Online (Sandbox Code Playgroud)
并遍历它,以便按顺序产生从1到18的数字.
我正在努力使用(genA,genB,genC)解决这个简单的例子,genA产生的值来自(1,4,7,10,13,16),genB产生(2,5,8,11,14)和genC屈服(3,6,9,12,15,17,18).
为了解决元组元组的简单问题,如果元组的元素长度相同,答案就相当简单.如果变量'a'指向元组,则可以使用
[i for t in zip(*a) for i in t]
Run Code Online (Sandbox Code Playgroud)
不幸的是,这些项目的长度不一定相同,拉链技巧似乎也不适用于发电机.
到目前为止,我的代码非常难看,而且我没有找到任何接近干净解决方案的东西.救命?
>>> list([e for e in t if e is not None] for t in itertools.izip_longest(*some_gen,
fillvalue=None))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17], [18]]
>>>
Run Code Online (Sandbox Code Playgroud)
您可能会考虑itertools.izip_longest,但如果 None 是有效值,则该解决方案将失败。这是一个示例“另一个生成器”,它完全符合您的要求,并且非常干净:
def my_gen(generators):
while True:
rez = ()
for gen in generators:
try:
rez = rez + (gen.next(),)
except StopIteration:
pass
if rez:
yield rez
else:
break
print [x for x in my_gen((iter(xrange(2)), iter(xrange(3)), iter(xrange(1))))]
[(0, 0, 0), (1, 1), (2,)] #output
Run Code Online (Sandbox Code Playgroud)