ActiveState Code

Recipe 103702: unzip


Inverse of zip

Python
 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)

Comments

  1. 1. At 2:27 p.m. on 25 aug 2002, Christophe Delord said:

    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))
    
  2. 2. At 8:04 p.m. on 27 apr 2003, Peter Scott said:

    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?

  3. 3. At 3:39 p.m. on 20 may 2003, Sudhir Kumar said:

    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

  4. 4. At 2:07 p.m. on 6 jun 2003, Denis Kaznadzey said:

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

    such unzip is actually a matrix transposer;

    also unzip (unzip (ll)) == ll

  5. 5. At 6:51 p.m. on 1 mar 2004, Michael Hartl said:

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

  6. 6. At 12:53 p.m. on 8 mar 2004, Michael Hartl said:

    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),)]
    
  7. 7. At 12:56 p.m. on 8 mar 2004, Michael Hartl said:

    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.

  8. 8. At 2:37 p.m. on 24 may 2005, Frank P Mora said:

    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'}
    

Sign in to comment