我注意到itertools
没有(在我看来)有一个函数能够交错来自其他几个可迭代对象的元素(而不是压缩它们):
def leaf(*args): return (it.next() for it in cycle(imap(chain,args)))
tuple(leaf(['Johann', 'Sebastian', 'Bach'], repeat(' '))) => ('Johann', ' ', 'Sebastian', ' ', 'Bach', ' ')
(编辑)我问的原因是因为我想避免不必要的拉链/展平事件。
显然,leaf
的定义很简单,但是如果有预定义的函数执行相同的操作,我宁愿使用它,也可以使用非常清晰的生成器表达式。 是否内置了这样的函数,在itertools中,或者在其他一些着名的库中,还是一个合适的惯用表达式?
编辑2:可以使用更简洁的定义(使用functional
包):
from itertools import *
from functional import *
compose_mult = partial(reduce, compose)
leaf = compose_mult((partial(imap, next), cycle, partial(imap, chain), lambda *args: args))
答案 0 :(得分:10)
您正在寻找内置的zip
和itertools.chain.from_iterable
来平展结果:
>>> import itertools
>>> list(zip(['Johann', 'Sebastian', 'Bach'], itertools.repeat(' ')))
[('Johann', ' '), ('Sebastian', ' '), ('Bach', ' ')]
>>> list(itertools.chain.from_iterable(_))
['Johann', ' ', 'Sebastian', ' ', 'Bach', ' ']
请注意,我使用list
只是为了强制输出一个好的。使用标准的itertools,leaf
的替代实现将是:
leaf = lambda *a: itertools.chain.from_iterable(itertools.izip(*a)) # Python 2.x
leaf = lambda *a: itertools.chain.from_iterable(zip(*a)) # Python 3.x
答案 1 :(得分:5)
itertools roundrobin() recipe将是我的第一选择,尽管在你的确切示例中它将产生无限序列,因为它以最长的可迭代而不是最短的顺序停止。当然,解决这个问题很容易。也许值得检查一下不同的方法?
答案 2 :(得分:0)
这个自定义函数交错迭代器并继续直到每个迭代器都用完
def interleave_iterators(*iterators):
finished = [False for x in range(len(iterators))]
stop_cond = functools.reduce(lambda x,y:not x or not y,finished)
while stop_cond:
for i,it in enumerate(iterators):
try:
yield next(it)
except StopIteration:
finished[i] = True
stop_cond = functools.reduce(lambda x,y:not x or not y,finished)
例如
it1 = iter([2,4,6,8])
it2 = iter([1,3,5,7,9,11,13])
for x in interleave_iterators(it1,it2): # prints 2 1 4 3 6 5 8 7 9 11 13
print(str(x),end=" ")