zip で 2 つのリストをペアにする

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

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 40

for 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] のときの遷移は次の通りです。

diagram (will load when visible)

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 つができることを確認しましょう。

  1. zip で組み合わせ の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. zip で組み合わせ とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. zip を使って 2 つのリストを並行して走査すること
  2. f-string でフォーマットすること
  3. 戻り値は 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)"]

ヒント

main.py
main.py
学習モード

メモ

zip で 2 つのリストをペアにする

⌘S で保存