Back to TILs.

Calmcode TIL

Unzip with `zip` logoUnzip with `zip`

In Python you can zip two iterables together.

i1 = 'abcde'
i2 = [1, 2, 3, 4, 5]
zipped = zip(i1, i2)

This zipped variable points to a new iterable that contains tuples of i1/i2 contents.

print(list(zipped))
# [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

This is all relatively straightforward, but how can you now go the other way around?

Reverse zip

Suppose now that we have a list of tuples. How might we turn this list of tuples into two iterables that split the integers from the characters?

tuples = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

It turns out that you can use zip again!

l1, l2 = zip(*tuples)
print(l1)
# ('a', 'b', 'c', 'd', 'e')
print(l2)
# (1, 2, 3, 4, 5)]

How does this work?

You may be suprised by this. How does a function for zipping also handle the unzipping?

Let's begin by understanding what zip() does when we pass it two lists with two items each.

print(list(zip(['a', 1], ['b', 2])))
# [('a', 'b'), (1, 2)]

It seems we're creating two tuples as output. One contains all the items at index 0. The other contains items at index 1.

So what would happen when we add another list?

print(list(zip(['a', 1], ['b', 2], ['c', 3])))
# [('a', 'b', 'c'), (1, 2, 3)]

Let's do one more.

print(list(zip(['a', 1], ['b', 2], ['c', 3], ['d', 4])))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

So what if we have an iterable of tuples? Well ... we can unpack them.

l1, l2 = zip(*tuples)

Back to main.