297

I have a list of tuples l = [(1,2), (3,4), (8,9)]. How can I, succinctly and Pythonically, unzip this list into two independent lists, to get [ [1, 3, 8], [2, 4, 9] ]?

In other words, how do I get the inverse of what zip does?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
VaidAbhishek
  • 5,895
  • 7
  • 43
  • 59
  • 34
    `zip` is basically it's own inverse. It's pretty cute like that. :) – mgilson Oct 19 '12 at 12:45
  • 3
    `zip` is *not* it's own inverse. It is close though. A function that is its own inverse is called an *involution*. [This answer](https://stackoverflow.com/a/19343/1959808) uses `zip` to define an involution. – 0 _ Jun 12 '17 at 08:26
  • 3
    If you want to sort the values of X by the values of Y and return two separate lists after , you can do : `y,x= map(list,zip(*sorted(zip(y, x))))` – Ray Mar 15 '19 at 16:56

2 Answers2

522

Use zip(*list):

>>> l = [(1,2), (3,4), (8,9)]
>>> list(zip(*l))
[(1, 3, 8), (2, 4, 9)]

The zip() function pairs up the elements from all inputs, starting with the first values, then the second, etc. By using *l you apply all tuples in l as separate arguments to the zip() function, so zip() pairs up 1 with 3 with 8 first, then 2 with 4 and 9. Those happen to correspond nicely with the columns, or the transposition of l.

zip() produces tuples; if you must have mutable list objects, just map() the tuples to lists or use a list comprehension to produce a list of lists:

map(list, zip(*l))          # keep it a generator
[list(t) for t in zip(*l)]  # consume the zip generator into a list of lists
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 71
    Clever.... perhaps too clever. Anyone reading this without surrounding comments will scratch their head for some time. – speedplane Aug 26 '16 at 16:58
  • 2
    @speedplane: then put it in a function and name it `transpose()`. It's no more unreadable than many `numpy` or `pandas` operations; it's a bit specialist but does the job really well. – Martijn Pieters Aug 26 '16 at 17:00
  • 3
    In Python3, this creates a zip object. `>>> l = [(1,2), (3,4), (8,9)]` `>>> zip(*l)` `` which can be viewed with a list comprehension `>>> [ii for ii in zip(*l)]` `[(1, 3, 8), (2, 4, 9)]`. – amath Dec 12 '16 at 22:11
  • 14
    @amath: There is no need for a list comprehension. Just use `list()`: `list(zip(*l))`, much faster. – Martijn Pieters Dec 12 '16 at 22:12
  • 16
    **Beware**: `a, b = zip(*list)` will fail if `list` is empty so you'll have to treat empty as a special case. You won't get back two empty tuples - of course how could you? If this case can occur then it's much better to use a list comprehension instead. – Ian Goldby Sep 25 '17 at 15:38
  • 1
    @IanGoldby: or use exception handling. `try: a, b = zip(*list)`, `except ValueError: a, b = (), ()`. – Martijn Pieters Mar 28 '18 at 09:05
  • This creates a list of tuples, and not a list of lists like the question asked for... – Kapocsi Jan 09 '19 at 03:28
  • 3
    @Kapocsi: that's trivially addressed; if lists are needed just map the tuples to lists with a list comprehension. For the majority of use cases, producing sequences or even just iterables is enough. – Martijn Pieters Jan 09 '19 at 13:07
  • ```x , y = map(list, zip(*l) ``` – Rajan saha Raju Dec 07 '19 at 15:24
  • Is this memory efficient if l is a very long list? – Visionscaper May 22 '21 at 14:16
  • @Visionscaper in that case iterate over `zip(*long_list)` directly; `list(zip(*long_list))` would have to allocate enough memory for a new list plus a tuple per pair (iteration can potentially get away with reusing the same memoised tuple object). – Martijn Pieters May 23 '21 at 12:29
  • NB: you don't have to use list `x,y = tuple(zip(*((x,y) for x,y,_ in tuples))))` – CervEd Aug 08 '21 at 10:27
  • 1
    @CervEd: neither is needed. `x, y = zip(*((x, y) for x, y, _ in tuples))` would also work. As would `x, y = zip(*(xy for *xy, _ in tuples))`. – Martijn Pieters Aug 16 '21 at 11:52
  • In case you have **nested lists** of (x,y) pairs and want to separate them as list of lists of x and y, you just need to iterate the previous procedure for each nested list: `x, y = zip(*[ zip(*[ (x, y) for a in range(3) ]) for b in range(5)])` (or `map(list, zip(*[ map(list, zip(*[ (x, y) for a in range(3) ]) ) for b in range(5)]) )` if you want it as list of lists). – Puco4 Sep 12 '22 at 10:47
93

If you want a list of lists:

>>> [list(t) for t in zip(*l)]
[[1, 3, 8], [2, 4, 9]]

If a list of tuples is OK:

>>> zip(*l)
[(1, 3, 8), (2, 4, 9)]
  • 12
    I think `map(list, zip(*l))` is quite nice in Python 2.x. Anyway, +1 for option of list of lists :) – Jon Clements Oct 19 '12 at 12:45
  • 2
    I prefer list comprehension above `map` :) –  Oct 19 '12 at 12:46
  • @dav1d Interesting, do you have reference? –  Oct 19 '12 at 12:48
  • 6
    @dav1d -- That's not true. The speed of map vs. list-comp is entirely problem dependent (You'll see different timings from different people for different problems on SO relatively frequently). `map` + `lambda` is usually slower though ... The nice thing about a list-comp is that it's the same in py2k and py3k. – mgilson Oct 19 '12 at 12:49
  • 1
    @dav1d -- Here's an older, but classic [post](http://stackoverflow.com/questions/1247486/python-list-comprehension-vs-map) which shows the opposite (and the results still hold for me using python2.7 on OS-X) – mgilson Oct 19 '12 at 12:52
  • Ok, I should rephrase, a `LC` is mostly faster than `map`. And no I don't have a reference, but I made a few tests back in 2.6 time and redid them with 2.7 and map was always slower. – dav1d Oct 19 '12 at 12:53
  • @mgilson interesting, in my tests the LC was always faster. – dav1d Oct 19 '12 at 12:53
  • Great this also works when l itself is a tuple, 2-dimension tuple I mean – lsheng Jun 12 '14 at 00:49