I have two iterators, a list
and an itertools.count
object (i.e. an infinite value generator). I would like to merge these two into a resulting ite
Using itertools.izip(), instead of zip() as in some of the other answers, will improve performance:
As "pydoc itertools.izip" shows: "Works like the zip() function but consumes less memory by returning an iterator instead of a list."
Itertools.izip will also work properly even if one of the iterators is infinite.
You can use zip
as well as itertools.chain
. This will only work if the first list is finite:
merge=itertools.chain(*[iter(i) for i in zip(['foo', 'bar'], itertools.count(1))])
You can do something that is almost exaclty what @Pramod first suggested.
def izipmerge(a, b):
for i, j in itertools.izip(a,b):
yield i
yield j
The advantage of this approach is that you won't run out of memory if both a and b are infinite.
I prefer this other way which is much more concise:
iter = reduce(lambda x,y: itertools.chain(x,y), iters)
I also agree that itertools is not needed.
But why stop at 2?
def tmerge(*iterators):
for values in zip(*iterators):
for value in values:
yield value
handles any number of iterators from 0 on upwards.
UPDATE: DOH! A commenter pointed out that this won't work unless all the iterators are the same length.
The correct code is:
def tmerge(*iterators):
empty = {}
for values in itertools.izip_longest(*iterators, fillvalue=empty):
for value in values:
if value is not empty:
yield value
and yes, I just tried it with lists of unequal length, and a list containing {}.
A generator will solve your problem nicely.
def imerge(a, b):
for i, j in itertools.izip(a,b):
yield i
yield j