我有两个迭代器,一个list
和一个itertools.count
对象(即无限值生成器).我想将这两个合并到一个生成的迭代器中,它将在两者之间交替屈服值:
>>> import itertools >>> c = itertools.count(1) >>> items = ['foo', 'bar'] >>> merged = imerge(items, c) # the mythical "imerge" >>> merged.next() 'foo' >>> merged.next() 1 >>> merged.next() 'bar' >>> merged.next() 2 >>> merged.next() Traceback (most recent call last): ... StopIteration
这样做最简单,最简洁的方法是什么?
发电机可以很好地解决您的问题.
def imerge(a, b): for i, j in itertools.izip(a,b): yield i yield j
你可以做一些几乎与@Pramod最初建议的事情相似的事情.
def izipmerge(a, b): for i, j in itertools.izip(a,b): yield i yield j
这种方法的优点是,如果a和b都是无限的,你就不会耗尽内存.
我也同意不需要itertools.
但为什么要停在2?
def tmerge(*iterators): for values in zip(*iterators): for value in values: yield value
从0开始处理任意数量的迭代器.
更新:DOH!一位意见提供者指出,除非所有迭代器的长度相同,否则这将不起作用.
正确的代码是:
def tmerge(*iterators): empty = {} for values in itertools.izip_longest(*iterators, fillvalue=empty): for value in values: if value is not empty: yield value
是的,我只是用不等长的列表和一个包含{}的列表来尝试它.
我会做这样的事情.这将是最节省时间和空间的,因为您不会有将对象压缩在一起的开销.这也将工作,如果这两个a
和b
是无限的.
def imerge(a, b): i1 = iter(a) i2 = iter(b) while True: try: yield i1.next() yield i2.next() except StopIteration: return
您可以使用zip
以及itertools.chain
.这仅在第一个列表有限时才有效:
merge=itertools.chain(*[iter(i) for i in zip(['foo', 'bar'], itertools.count(1))])