Definition:Zipping
zip操作とは、複数の系列(sequence)の同じ位置にある要素を相互に対応付け、それらを組(tupleなど)としてまとめる操作のことをいう。
2つの系列
A = [a₁, a₂, ..., aₙ]
B = [b₁, b₂, ..., bₘ]
に対して、zip操作は
[(a₁,b₁), (a₂,b₂), ..., (aₖ,bₖ)]
という系列を生成する。ここで k = min(n,m) であり、通常のzipでは最も短い系列の長さに達した時点で操作を終了する。
例えば、
zip([1, 2, 3], ["a", "b", "c"])
は、
[(1, "a"), (2, "b"), (3, "c")]
に相当する。
さらに一般化すると、zip操作は複数の系列を、それぞれの要素の位置(index)をキーとして横断的に対応付ける操作である。
| 言語 | 操作・関数 | 内容 |
|---|---|---|
| Python | zip() | 複数の系列を同じ位置で対応付ける |
| JavaScript | zip()は標準ではない | map()などを組み合わせて同様の処理ができる |
| Ruby | zip() | 配列を同じ位置で対応付ける |
| Haskell | zip | 2つのリストを対応付ける |
| Scala | zip | コレクションを対応付ける |
| Rust | zip() | Iterator同士を対応付ける |
| Kotlin | zip() | 2つのコレクションを対応付ける |
| Clojure | mapなど | Pythonのzip()に相当する処理を別の形で行う |
names = ["Alice", "Bob", "Carol"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f"{name}: {score}点")
出力:
Alice: 85点
Bob: 92点
Carol: 78点
zip() は複数のリストを同じインデックスの要素同士でペアにして1つずつ取り出す。names[i] と scores[i] をインデックスで対応付ける代わりに、2つのリストを直接組にして走査できる。
リストの長さが異なる場合は、短い方に合わせて打ち切られる。
a = [1, 2, 3]
b = ["x", "y"]
print(list(zip(a, b))) # [(1, 'x'), (2, 'y')] ← 3は無視される
同じインデックス同士を掛け合わせる場合:
a = [1, 2, 3, 4]
b = [10, 20, 30, 40]
# 同じインデックス同士を掛け合わせる
products = [x * y for x, y in zip(a, b)]
print(products) # [10, 40, 90, 160]
ひとつずらして掛け合わせる場合は、リストを1つ分ずらしたものと元のリストを zip() で組ませればよい。
values = [1, 2, 3, 4, 5]
# 隣り合う要素同士を掛け合わせる(1つずらして掛け合わせる)
shifted_products = [x * y for x, y in zip(values, values[1:])]
print(shifted_products) # [2, 6, 12, 20]
values[1:] は先頭を1つ落としたリスト [2, 3, 4, 5] になるので、zip(values, values[1:]) は (1,2), (2,3), (3,4), (4,5) という隣接ペアを作る。ずらし幅を増やせば、2つ・3つ離れた要素同士の掛け合わせも同様に書ける。
# 2つ離れた要素同士を掛け合わせる
gap2_products = [x * y for x, y in zip(values, values[2:])]
print(gap2_products) # [3, 8, 15]
Mathematics is the language with which God has written the universe.