Zip list with several elements

I am trying to enhance zip_with_scalar logic. I am trying to zip with a vector

So far I have achieved this -

import itertools

def zip_with_vector(l, o):
    if not isinstance(o, list):
        return zip(l, itertools.repeat(o))
    else:
        for e in o:
            l = list(zip_with_vector(l, e))

    return l

print(list(zip_with_vector(['a', 'b', 'c'], ['x', 'y', 'z'])))

>>> [((('a', 'x'), 'y'), 'z'), ((('b', 'x'), 'y'), 'z'), ((('c', 'x'), 'y'), 'z')]

but I want as this [('a', 'x', 'y', 'z'), ('b', 'x', 'y', 'z'), ('c', 'x', 'y', 'z')]

I know I am close but not able to figure out the recursion logic.

Upvotes: 1

Views: 173

Answers (2)

Avish
Avish

Reputation: 4626

If you want a sequence of "each element of the input list, concatenated with the input vector", then write just that:


def zip_with_vector(l, v):
  return ((elem,) + tuple(v)
          for elem in l)

list(zip_with_vector(['a', 'b', 'c'], ['x', 'y', 'z']))
>>> [('a', 'x', 'y', 'z'), ('b', 'x', 'y', 'z'), ('c', 'x', 'y', 'z')]

If this is indeed what you're looking for, then I don't see a need for recursion here.

As @Georgy mentioned in the comments, this can be written more concisely (and will probably execute faster) thus:

def zip_with_vector(l, v):
  return ((elem, *v) for elem in l)

Upvotes: 4

Georgy
Georgy

Reputation: 13697

You can extend zip_with_scalar to zip_with_vector by mapping itertools.repeat to each element of the vector:

def zip_with_vector(iterable, vector):
    return zip(iterable, *map(itertools.repeat, vector))
>>> list(zip_with_vector(['a', 'b', 'c'], ['x', 'y', 'z']))
[('a', 'x', 'y', 'z'), ('b', 'x', 'y', 'z'), ('c', 'x', 'y', 'z')]

Upvotes: 2

Related Questions