unzip function?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Jan 18 18:20:44 EST 2012

On Wed, 18 Jan 2012 11:20:00 -0500, Devin Jeanpierre wrote:

> On Wed, Jan 18, 2012 at 10:27 AM, Steven D'Aprano
> <steve+comp.lang.python at pearwood.info> wrote:
>>> That zip (*sorted...
>>> does the unzipping.
>>> But it's less than intuitively obvious.
>> *shrug*
>> If you understand what zip does, it should be obvious.
> Nobody likes to be told the thing they're confused about is trivial.

Nobody likes to be told to brush their teeth, eat their vegetables or 
clean their room. Then they grow up and learn that life is full of things 
that you do because you have to, not because you want to.

Learning that some things that they are confused about are trivial is one 
of those things.

> It's especially bad if nobody ever actually explains what's so simple
> about it. Saying it's "almost its own inverse" is just restating the
> original question -- yes, that's what it is, but why? (I have put my own
> interpretation in a separate reply. )

Because that's the nature of the Universe. 

That's just the way the zip operation works. It is a little more 
complicated, but no more mysterious, than the idea that you don't need 
separate reverse() and unreverse() methods. If you reverse a list, and 
then reverse it again, you get back the original order.

The only complication is that you can't just pass the result of zip back 
to zip directly, you have to use the unpack operator * to split the 
result "one sequence of N subsequences" into N separate arguments.

But apart from that complication, if you zip a bunch of sequences, then 
zip it again, you get back the original order. You describe that as 
taking the transpose of a matrix, which is correct, but that just puts a 
name to it, it doesn't explain *why* taking the transpose twice gives you 
the original matrix.

If you have a function that zips up items from multiple sequences, it 
takes the first item from each sequence and puts them together, then does 
the same thing with the second item from each sequence, the third item, 
and so forth:

zip([a1, a2, a3, ...], [b1, b2, b3, ...], [c1, c2, c3, ...], ...)
=> [(a1, b1, c1, ...), (a2, b2, c2, ...), (a3, b3, c3, ...), ...]

If you take that resulting list-of-sequences, expand it to separate 
arguments, and pass them to zip again:

zip((a1, b1, c1, ...), (a2, b2, c2, ...), (a3, b3, c3, ...), ...)

the zip function will zip the items up exactly in the same way, giving:

[(a1, a2, a3, ...), (b1, b2, b3, ...), (c1, c2, c3, ...), ...]

which naturally reverses the process. (Except that it returns a list of 
tuples instead of a list of lists.)


More information about the Python-list mailing list