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