zip(*zip(x, y)) in PythonHow zip can both pack and unpack like magic!
zip in Python?The built-in zip() function pairs up elements from multiple iterables.
x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
print(list(zipped)) # [(1, 4), (2, 5), (3, 6)]
Now hereโs something interesting:
x2, y2 = zip(*zip(x, y))
print(x2) # (1, 2, 3)
print(y2) # (4, 5, 6)
Letโs break it down.
zip(x, y)Combines the elements pair-wise:
[(1, 4), (2, 5), (3, 6)]
*zip(x, y) โ UnpackingThe asterisk * unpacks the list of pairs into separate arguments:
zip((1, 4), (2, 5), (3, 6))
So it's like we're zipping the columns of the original pair list.
It transposes the data โ rows become columns:
zip(*[(1, 4), (2, 5), (3, 6)])
โ zip((1, 4), (2, 5), (3, 6))
โ [(1, 2, 3), (4, 5, 6)]
You get:
x2 = (1, 2, 3)
y2 = (4, 5, 6)
So this line:
x2, y2 = zip(*zip(x, y))
is a way to unzip or reverse the original zip operation.
x == list(x2) and y == list(y2) # True
Everything matches โ zip/unzip is successful!
You can find this trick (and more like it) in the official Python zip() documentation here:
๐ https://docs.python.org/3/library/functions.html#zip
It even includes this line:
โAn idiom for clustering a data series into n-length groups using
zip(*[iter(s)]*n).โ
| Expression | Meaning |
|---|---|
zip(x, y) | Combine x and y into pairs |
zip(*zip(x, y)) | Reverse the zip โ unzip it! |
* operator | Unpacks zipped list into arguments |
This is one of those Pythonic idioms that feels a bit magical โ but now you know the logic behind it ๐ฅ