概要(zip のアンパックは「行と列をひっくり返す」基本テクニック)
zip は複数のイテラブルを「対応する位置でペア化」する関数です。アンパック(*演算子)を組み合わせると、zip で作ったペアを「元の列」へ戻したり、2次元データの行列転置を一行で実現できます。要点は「zip は最短の長さに揃える」「アンパックは“イテラブルを個別の引数に展開する”」の2つ。これを体に入れると、データ整形が驚くほど短く安全に書けます。
基本の使い方(ここが重要)
ペアのリストを“元の2列”へ戻す(アンパックで解凍)
zip が作ったペア(タプル)の並びを、*でアンパックして zip へそのまま渡すと「列の分解(unzip)」ができます。
pairs = [("alice", 25), ("bob", 30), ("charlie", 35)]
names, ages = zip(*pairs)
print(names) # ('alice', 'bob', 'charlie')
print(ages) # (25, 30, 35)
Pythonタプルで返るので、必要なら list(…) に変換します。
行列の転置(2次元リストの行⇔列入れ替え)
「行のリスト」をアンパックして zip に渡すと、列方向で束ねられます。一行で転置が完了します。
matrix = [
[1, 2, 3],
[4, 5, 6],
]
transposed = list(zip(*matrix))
print(transposed) # [(1,4), (2,5), (3,6)]
Python元がリストなら、列もリストで欲しい場合は map(list, …) を組み合わせます。
transposed_lists = list(map(list, zip(*matrix)))
Python複数列の同期処理(zip で並列、アンパックで分解)
zip で同時に処理した後、結果をアンパックして別々の列へ戻せます。
names = ["alice", "bob", "charlie"]
scores = [70, 85, 92]
paired = list(zip(names, scores)) # 並列処理しやすい形
# ... 何か処理した後で分解
new_names, new_scores = zip(*paired)
Python重要ポイントの深掘り(長さの扱い・一回性・型整形)
zip は「最短の長さ」に揃える(余りは捨てられる)
zip(a, b) は、短い方の要素数に合わせて打ち切られます。欠損を埋めたいなら itertools.zip_longest を使います(埋め値 fillvalue を指定)。
from itertools import zip_longest
a = [1, 2, 3]
b = ["x", "y"]
print(list(zip(a, b))) # [(1, 'x'), (2, 'y')]
print(list(zip_longest(a, b, fillvalue=None))) # [(1,'x'), (2,'y'), (3,None)]
Python転置やアンパックでは「列長が揃っている」ことが前提になるため、前処理で合わせるのが安全です。
zip オブジェクトは「一度きり」。必要なら list へ
zip(…) は遅延生成のイテレータです。一度反復すると使い切るため、後で再利用するなら list(…) にしておきます。
z = zip([1, 2], ["a", "b"])
print(list(z)) # 使い切る
# print(list(z)) # 空(再利用不可)
Pythonアンパック結果はタプルになる。用途に応じて変換する
アンパック+zip の戻りはタプル列です。ループに流すだけならそのままで十分、更新が必要なら list へ変換します。
cols = list(zip(*[[1,2,3],[4,5,6]])) # 列タプルのリスト
cols_lists = [list(c) for c in cols] # 列をリスト化
Python実務での使いどころ(転置・整形・マージ)
CSV の列⇔行変換(ヘッダ付きデータの転置)
ヘッダ行とデータ行の「列ごとの集計」や「縦持ち・横持ちの変換」に役立ちます。
rows = [
["name", "alice", "bob"],
["score", 70, 85],
["age", 25, 30],
]
cols = list(zip(*rows)) # 列方向へ
print(cols)
Python辞書化・結合の前処理(キー列と値列の合体/分解)
zip でキーと値を結合して辞書へ、アンパックで列へ戻して検証や再構成ができます。
keys = ["id", "name", "age"]
vals = [101, "alice", 25]
d = dict(zip(keys, vals))
# 後で列へ戻す例
kk, vv = zip(*d.items())
Python同時ソートや並列加工(複数列を一緒に並べ替え)
列を zip で束ねてソートし、アンパックで列へ戻すと「対応関係を保ったまま」並べ替えできます。
names = ["alice", "bob", "charlie"]
scores = [92, 85, 70]
paired = sorted(zip(scores, names), reverse=True) # スコア降順
sorted_scores, sorted_names = zip(*paired)
print(sorted_names) # ('alice','bob','charlie')
Python例題で身につける(定番から一歩先まで)
例題1:ペア配列を列へ分解(unzip)
pairs = [(1, "one"), (2, "two"), (3, "three")]
nums, words = zip(*pairs)
print(nums) # (1, 2, 3)
print(words) # ('one','two','three')
Python例題2:行列転置を一行で
M = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
T = list(map(list, zip(*M)))
print(T) # [[1,4,7],[2,5,8],[3,6,9]]
Python例題3:列を保ったソートとアンパック
names = ["A","B","C","D"]
heights= [160,170,165,155]
paired = sorted(zip(heights, names)) # 身長で昇順
heights_s, names_s = zip(*paired)
print(list(names_s)) # ['D','A','C','B']
Python例題4:長さ不一致を zip_longest で安全転置
from itertools import zip_longest
rows = [
["name", "alice", "bob"],
["score", 70],
]
cols = list(zip_longest(*rows, fillvalue=None))
print(cols) # 列長不一致でも転置可能
Pythonまとめ
zip は「複数列を対応位置で束ねる」、アンパックは「束ねたものを列にほどく」。この組み合わせで、行列転置、ペアの分解、対応関係を保った並列加工とソートが一気に短く、正確に書けます。必須の注意点は、zip が最短列に合わせて打ち切ること、zip オブジェクトは一回きりなこと、アンパックの戻りがタプルであること。長さ不一致には zip_longest、列の型整形には map(list, …) を使い分ける。まずは「zip で束ねる→*で解く」を標準手段として手に馴染ませましょう。
