1

Is there a more concise and time efficient way to achieve the following zip operation in Python? I am pairing lists of lists together to make new lists, as follows:

>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[10, 11, 12], [13, 14, 15]]
>>> for x, y in zip(a, b):
...   print zip(*[x, y])
... 
[(1, 10), (2, 11), (3, 12)]
[(4, 13), (5, 14), (6, 15)]

thanks.

4 Answers 4

6

I don't really see a better way other than replacing:

print zip(*[x, y])

with:

print zip(x,y)

If you're really working with 2 element lists, you could probably just do:

print zip( a[0], b[0] )
print zip( a[1], b[1] )

(It'll be slightly more efficient as you leave off 1 zip, but I'm not convinced that it is more clear, which is what you should really be worried about).


If you're really into compact code, you can use map:

map(zip,a,b) #[[(1, 10), (2, 11), (3, 12)], [(4, 13), (5, 14), (6, 15)]]

Which again might be more efficient than the other version, but I think you pay a slight price in code clarity (though others may disagree).

Sign up to request clarification or add additional context in comments.

4 Comments

@KayZhu -- Yeah, I wasn't sure if I wanted to mention it simply because you don't see multiple argument map very often. Since it's not a particularly familiar idiom I hesitate to use it ... But I don't think you'll find a way to do it in less characters ...
yes I would agree that I'd prefer the existing code without map. But it's good to know there's another, shorter way to do it :)
@KayZhu -- I also always thought it was a little funny that map(None,a,b) is basically a list(izip_longest(a,b,fillvalue=None))
I knew there was a neat map-based oneliner in here somewhere, but it didn't occur to me to pass the arguments to map separately. My thought was to use starmap: list(itertools.starmap(zip, zip(a, b))).
3
>>> [zip(i, j) for i, j in zip(a,b)]
[[(1, 10), (2, 11), (3, 12)], [(4, 13), (5, 14), (6, 15)]]

Of course, this is really just the same thing that you wrote above.

Comments

2

In addition to what @mgilson said, you can also consider using itertools.izip if the lists you are zipping are big.

Since izip computes elements only when requested and only returns an iterator, the memory usage is much less than zip for large lists.

Comments

1

This works well too:

print zip(sum(a,[]),sum(b,[]))

prints:

[(1, 10), (2, 11), (3, 12), (4, 13), (5, 14), (6, 15)]

This is probably the best performance wise and is concise as well:

from itertools import chain
print zip(chain(*a),chain(*b))

same output

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.