I noticed that itertools
does not (it seems to me) have a function capable of interleaving elements from several other iterable objects (as opposed to zipping them):
def leaf(*args): return (it.next() for it in cycle(imap(chain,args)))
tuple(leaf(['Johann', 'Sebastian', 'Bach'], repeat(' '))) => ('Johann', ' ', 'Sebastian', ' ', 'Bach', ' ')
(Edit) The reason I ask is because I want to avoid unnecessary zip/flatten occurrences.
Obviously, the definition of leaf
is simple enough, but if there is a predefined function that does the same thing, I would prefer to use that, or a very clear generator expression. Is there such a function built-in, in itertools, or in some other well-known library, or a suitable idiomatic expression?
Edit 2: An even more concise definition is possible (using the functional
package):
from itertools import *
from functional import *
compose_mult = partial(reduce, compose)
leaf = compose_mult((partial(imap, next), cycle, partial(imap, chain), lambda *args: args))
Python generators are a simple way of creating iterators. All the work we mentioned above are automatically handled by generators in Python. Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).
Generator-Function : A generator-function is defined like a normal function, but whenever it needs to generate a value, it does so with the yield keyword rather than return. If the body of a def contains yield, the function automatically becomes a generator function.
You need to call next() or loop through the generator object to access the values produced by the generator expression. When there isn't the next value in the generator object, a StopIteration exception is thrown. A for loop can be used to iterate the generator object.
You're looking for the built-in zip
and itertools.chain.from_iterable
to flatten the result:
>>> import itertools
>>> list(zip(['Johann', 'Sebastian', 'Bach'], itertools.repeat(' ')))
[('Johann', ' '), ('Sebastian', ' '), ('Bach', ' ')]
>>> list(itertools.chain.from_iterable(_))
['Johann', ' ', 'Sebastian', ' ', 'Bach', ' ']
Note that I used list
just to force a nice output. Using the standard itertools, alternative implementations for leaf
would be:
leaf = lambda *a: itertools.chain.from_iterable(itertools.izip(*a)) # Python 2.x
leaf = lambda *a: itertools.chain.from_iterable(zip(*a)) # Python 3.x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With