# 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.)

--
Steven

```