If a function gets passed an undefined number of iterables N of arbitrary length M, is there a way to obtain a generator that yield M tuples of size N containing the elements of the passed iterables?
def dispatch(*iterables):
args = ( some kind of generator that involves *iterables)
for _ in args:
yield _
In other words, if we consider *iterables as an NxM matrix in which each column (function argument) is an iterable is there a way using a generator to yield the rows of the matrix?
Eg:
a = [9,8,7,6]
b = 'ciao'
c = iter(range(0,4))
>>> res = dispatch(a,b,c)
>>> res.__next__()
(9,c,0)
>>> res.__next__()
(8,i,1)
etc...
furthermore since this function could also take only 1 iterable as argument, the generator should be able to handle the case and output something like:
a = [9,8,7,6]
>>> res = dispatch(a)
>>> res.__next__()
(9,)
>>> res.__next__()
(8,)
I tried using zip but it doesn't handle the aforementioned edge case, plus it is kind of slow, which suggest that it probably has to read the whole thing before producing an output.
You can use map
combined with a lambda
that pack the arguments:
>>> list(map(lambda *x: tuple(x), range(10), range(10), range(10)))
[(0, 0, 0), (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6), (7, 7, 7), (8, 8, 8), (9, 9, 9)]
>>> list(map(lambda *x: tuple(x), range(10)))
[(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,)]
Your function would be really simple:
def dispatch(*args):
return map(lambda *x: tuple(x), *args)
As in your example:
>>> a = [9,8,7,6]
>>> b = 'ciao'
>>> c = iter(range(0,4))
>>> list(dispatch(a, b, c))
[(9, 'c', 0), (8, 'i', 1), (7, 'a', 2), (6, 'o', 3)]