Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Traversing a sequence of generators

I have a sequence of generators: (gen_0, gen_1, ... gen_n)

These generators will create their values lazily but are finite and will have potentially different lengths.

I need to be able to construct another generator that yields the first element of each generator in order, followed by the second and so forth, skipping values from generators that have been exhausted.

I think this problem is analogous to taking the tuple

((1, 4, 7, 10, 13, 16), (2, 5, 8, 11, 14), (3, 6, 9, 12, 15, 17, 18))

and traversing it so that it would yield the numbers from 1 through 18 in order.

I'm working on solving this simple example using (genA, genB, genC) with genA yielding values from (1, 4, 7, 10, 13, 16), genB yielding (2, 5, 8, 11, 14) and genC yielding (3, 6, 9, 12, 15, 17, 18).

To solve the simpler problem with the tuple of tuples the answer is fairly simple if the elements of the tuple were the same length. If the variable 'a' referred to the tuple, you could use

[i for t in zip(*a) for i in t]

Unfortunately the items are not necessarily the same length and the zip trick doesn't seem to work for generators anyway.

So far my code is horribly ugly and I'm failing to find anything approaching a clean solution. Help?

like image 435
Sean Holdsworth Avatar asked Jan 17 '13 11:01

Sean Holdsworth


People also ask

What is Islice?

islice(iterable, start, stop[, step]) Make an iterator that returns selected elements from the iterable. If start is non-zero, then elements from the iterable are skipped until start is reached. Afterward, elements are returned consecutively unless step is set higher than one which results in items being skipped.

Which is better iterator or generator in Python?

Generators provide a better way to create iterators in Python. This can be done by defining a proper function instead of using a return statement that uses a yield keyword.

Are all iterators generators?

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions ( yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator .

What is the difference between generator and iterator?

Iterators are the objects that use the next() method to get the next value of the sequence. A generator is a function that produces or yields a sequence of values using a yield statement. Classes are used to Implement the iterators. Functions are used to implement the generator.


1 Answers

I think you need itertools.izip_longest

>>> list([e for e in t if  e is not None] for t in itertools.izip_longest(*some_gen,
                                                               fillvalue=None))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17], [18]]
>>> 
like image 50
Abhijit Avatar answered Sep 25 '22 02:09

Abhijit