zip で 2 つのリストをペアにする
zip で 2 つのリストをペアにする とは
zip 関数を使って、2 つのリストの要素を順番にペアにしながら処理する基本パターンを学ぶ。本レッスンでは、zip で 2 つのリストをペアにする の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
zip で 2 つのリストをペアにする
複数のリストを 同じインデックスでペア にしながら処理したいことはよくあります。例えば「商品名のリストと価格のリストを並べて表示する」「英単語と日本語訳をペアにして辞書を作る」といった場面です。Python ではこういうときに組み込みの zip 関数を使うのが定番です。本レッスンでは、zip を使って 2 つのリストを横並びにループするパターンを学びます。
zip は名前のとおり、ジッパーのようにリスト同士を噛み合わせていくイメージです。
zip の基本
zip(iter_a, iter_b, ...) は、複数のイテラブルから 1 要素ずつ取り出して タプル にまとめたイテレータを返します。要素数が違うときは、短い方 に合わせて打ち切られるのも重要な性質です。
Python
names = ['Alice', 'Bob', 'Carol']
ages = [30, 25, 40]
for name, age in zip(names, ages):
print(name, age)
# Alice 30
# Bob 25
# Carol 40for name, age in zip(...) のようにアンパックすれば、ペアの 1 つ目を name、2 つ目を age として受け取れます。タプルが分かっていれば、zip はそのタプルを順番に作っているだけだ、と理解できます。
zip は遅延評価。リストにしたいときは list(zip(...)) で囲みます。
ペアを文字列に整形する
本レッスンの課題は、名前のリストと年齢のリストを受け取り、'Alice(30)' のように整形した文字列リストを返すことです。zip と f-string を組み合わせると、たったの数行で書けます。
Python
def pair_name_age(names, ages):
result = []
for name, age in zip(names, ages):
result.append(f'{name}({age})')
return result上のコードは names = ['Alice', 'Bob']、ages = [30, 25] のとき ['Alice(30)', 'Bob(25)'] を返します。zip は短い方に合わせるので、names の方が長くても余りは無視されます。逆に「余りも欲しい」ときは itertools.zip_longest を使う、と知っておくと後々便利です。
zip は何個でも引数を取れるので、3 つ以上のリストを同時に回すこともできます。
動きを追ってみる
names = ['Alice', 'Bob']、ages = [30, 25] のときの遷移は次の通りです。
zip は要求されるたびに次のタプルを 1 個作るだけです。for の各反復で「次のペアくれ」と頼まれた zip が、両方のリストから 1 要素ずつ取って tuple にして返してくれます。
よくある間違い
zip でつまずきやすいポイントは次の通りです。
- アンパックを忘れて
(name, age)のタプルで扱おうとする zipをそのままprintしてしまい、zip objectの文字列が表示される- 要素数が違うときに、長い方の余りも処理されると思い込む
- インデックスと混同して
zip(range(len(names)), names)のように冗長な書き方をする zipを一度使い切ると 空 になることを忘れる
Python
# NG: 短い方に合わせるので、余分な 'Dave' は無視される
names = ['Alice', 'Bob', 'Carol', 'Dave']
ages = [30, 25, 40]
list(zip(names, ages))
# [('Alice', 30), ('Bob', 25), ('Carol', 40)] Dave は出てこないこの挙動は 仕様 なので、長さがズレているときの方針 (切り詰めるのか、足りない方を埋めるのか) を意識して使い分けましょう。本レッスンの課題では、テストデータの長さは常に揃っているので心配いりません。zip は一度走り切ると 空 になるので、2 回繰り返したいときはその都度作り直してください。
複数のリストを並行して扱う場面では、zip を真っ先に思い出すと幸せになれます。
やってみよう
このレッスンでは、文字列リスト names と整数リスト ages を受け取り、'Alice(30)' のように名前と年齢を括弧で連結した文字列リストを返す関数 pair_name_age(names, ages) を実装します。zip でペアを取り出し、f'{name}({age})' で整形しましょう。空リストを渡されたら空リストを返します。
余裕があれば、
zipを使わずにenumerateだけで同じ処理を書いてみると、どれだけzipが便利か実感できます。
よくある質問
Q. 長さが違うリストを zip するとどうなりますか?
A. 短い方に合わせて打ち切られます。たとえば zip([1,2,3], ['a','b']) は [(1,'a'),(2,'b')] になります。打ち切らずに足りない部分を埋めたいときは itertools.zip_longest(fillvalue=None) を使ってください。
Q. zip の戻り値はリストですか?
A. Python 3 では zip オブジェクト(イテレータ)です。リストとして使いたいときは list(zip(...)) で変換してください。1 回しか走査できないため、複数回使う場合は list 化しておくと「2 回目が空」のバグを避けられます。
Q. zip を逆に使ってアンパックできますか?
A. list(zip(pairs)) でアンパックできます。[(1,'a'),(2,'b')] を [(1,2), ('a','b')] のように転置できるイディオムで、行と列を入れ替えるときによく使います。 で要素を展開している点がポイントです。
次のレッスン
次は break と continue でループを制御する で、zip 関数を使って、2 つのリストの要素を順番にペアにしながら処理する基本パターンを学ぶ を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- zip で組み合わせ の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. zip で組み合わせ とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- zip を使って 2 つのリストを並行して走査すること
- f-string でフォーマットすること
- 戻り値は return で返すこと
入出力例
test-cases.txt
pair_name_age(["Alice","Bob","Carol"], [30,25,40]) → ["Alice(30)","Bob(25)","Carol(40)"]
pair_name_age(["Eve"], [22]) → ["Eve(22)"]
pair_name_age([], []) → []
pair_name_age(["A","B","C"], [1,2]) → ["A(1)","B(2)"]
pair_name_age(["X"], [1,2,3]) → ["X(1)"]