Welcome, guest | Sign In | My Account | Store | Cart
1

Inverse of zip

Python, 13 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def unzip(args):
    """
    inverse of zip. Given: ((1,"a"),(2,"b")) --> ((1,2),("a","b"))

    seq == unzip(zip(seq)) if seq is a rectangular matrix (all of its row has the same length.
    """
    result = []
    n = min(map(len,args))
    for i in range(n):result.append([])
    for i in range(len(args)):
        for j in range(n):
            result[j].append(args[i][j])
    return tuple(result)

8 comments

Christophe Delord 12 years, 3 months ago  # | flag

unzip. A shorter version of unzip can be:

unzip = lambda l:tuple(zip(*l))

or for older Python versions:

unzip = lambda l:tuple(apply(zip,l))
Peter Scott 11 years, 7 months ago  # | flag

Why isn't this standard? This is very useful; I don't see why it isn't in the python standard library. When I'm doing heavy list manipulations this is extremely handy.

PEP anyone?

Sudhir Kumar 11 years, 6 months ago  # | flag

isn't zip its own inverse? >>> zip((1, 2), ('a', 'b'))

[(1, 'a'), (2, 'b')]

>>> zip((1,"a"),(2,"b"))

[(1, 2), ('a', 'b')]

Why do we need an unzip?

Thanks,

-- sudhir

Denis Kaznadzey 11 years, 5 months ago  # | flag

Simple unzip. unzip = lambda ll: apply (zip, ll)

such unzip is actually a matrix transposer;

also unzip (unzip (ll)) == ll

Michael Hartl 10 years, 9 months ago  # | flag

Another unzip. def unzip(seq): return zip(*seq)

Michael Hartl 10 years, 8 months ago  # | flag

Zip is not its own inverse. Zip isn't its own inverse in general, e.g.,

>>> zip(zip((1, 2, 3), (4, 5, 6), (7, 8, 9)))
[((1, 4, 7),), ((2, 5, 8),), ((3, 6, 9),)]
Michael Hartl 10 years, 8 months ago  # | flag

Redundancy. I just realized that this is equivalent to the first lambda expression on the top. Oh, well. It's redundant, but to my eye it looks more Pythonic.

Frank P Mora 9 years, 6 months ago  # | flag

Feed zip arguments correctly.

Zip *is* its own inverse.

You are giving your outer zip call a single argument. The inner zip
produces a single list of tuples. If you give zip a single argument
it will return what you are getting. If you precede any single list
with an asterisk in any function the function is passed len(list)
arguments.

Try this:

>>> zip( *zip( (1, 2, 3), (4, 5, 6), (7, 8, 9) ) )
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]

Kumar was manually separating the elements of his list. He was feeding
his second zip two arguments. He could have typed

>>> zip_out= zip((1, 2), ('a', 'b'))
>>> zip( *zip_out )
[(1, 2), ('a', 'b')]

and saved typing so he could focus on gaining more valuable insights.



The asterisk is necessary when using list compressions with zip.

>>> zip( *[ s.split() for s in (“a b c d e f g”, “t u v w x y z”) ] )
[('a', 't'), ('b', 'u'), ('c', 'v'), ('d', 'w'), ('e', 'x'), ('f', 'y'), ('g', 'z')]


Dictionaries are easily created in this fashion.

>>> dict( zip( *[ s.split() for s in (“Q1 Q2 Q3 Q4”, “Jan Apr Jul Oct”) ] ) )
{'Q1': 'Jan', 'Q3': 'Jul', 'Q2': 'Apr', 'Q4': 'Oct'}

Add a comment

Sign in to comment

Created by Andres Tuells on Tue, 18 Dec 2001 (PSF)
Python recipes (4279)
Andres Tuells's recipes (7)

Required Modules

  • (none specified)

Other Information and Tasks