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))
The itertools roundrobin() recipe would've been my first choice, though in your exact example it would produce an infinite sequence, as it stops with the longest iterable, not the shortest. Of course, it would be easy to fix that. Maybe it's worth checking out for a different approach?