Reputation: 321
I need a function which returns a tuple one at a time from a list of sequences without using zip . i tried to do it in this fashion:
gen1=[(x,y)for x in range(3) for y in range(4)]
which gives the following list:
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
next I tried to return one tuple at a time by:
next(gen1)
But an error occured that list is not 'iterable' . how can i do it using generators.
Upvotes: 1
Views: 815
Reputation: 5208
As of Python 2.4, you can do:
gen1 = ((x, y) for x in range(3) for y in range(4))
Note that you can always make a generator (well, iterator) from a list with iter
:
gen1 = iter([(x, y) for x in range(3) for y in range(4)])
The difference in usage will be none. The second way will require the whole list to be in memory, though, while the first will not.
Note that you can also use the builtin functionality of zip
, which is a generator (in Python 3). In Python 2, use itertools.izip
.
Python 3:
>>> zip(range(0, 5), range(3, 8))
<zip object at 0x7f07519b3b90>
>>> list(zip(range(0, 5), range(3, 8)))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]
Python < 3:
# Python < 3
>>> from itertools import izip
>>> izip(range(0, 5), range(3, 8))
<itertools.izip object at 0x7f5247807440>
>>> list(izip(range(0, 5), range(3, 8)))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]
>>> zip(range(0, 5), range(3, 8))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]
Upvotes: 1
Reputation: 21914
If you want the behavior to work with an arbitrary number of sequences, while there are still some ambiguities in the question, if what you're trying to do is just make a generator version of zip, the below should work well:
def generator_zip(*args):
iterators = map(iter, args)
while iterators:
yield tuple(map(next, iterators))
First it turns each arg into an iterator, then continues to yield tuple that include the next relevant entry from each iterator until the shortest list is exhausted.
Upvotes: 1