こんにちは、かつコーチです。
「名前のリストと年齢のリストがあるけど、これを一緒にループしたい」
そんな場面で役立つのがzip()です。
インデックスを使って無理やり結合するコードを書いた経験がある方も多いのではないでしょうか。
この記事では、zip()の基本構文から、複数リストの同時ループ、辞書への変換方法まで解説します。
読み終える頃には、複数のリストをスマートに扱えるようになります。
zip()の基本構文
zip()は複数のイテラブルをまとめる関数
zip()は、複数のイテラブル(リストやタプルなど、繰り返し処理できるデータ)を受け取り、それぞれの要素を組にしたzipオブジェクトを返す組み込み関数です。
names = ["田中", "佐藤", "鈴木"]
ages = [28, 22, 35]
zipped = zip(names, ages)
print(zipped)
print(list(zipped))
実行結果は次の通りです。
<zip object at 0x1035a5d80>
[('田中', 28), ('佐藤', 22), ('鈴木', 35)]
zip()の結果はそのままでは中身が見えないため、list()で囲んでリストに変換すると確認しやすくなります。
複数リストを同時にループする
zip()の最大の使いどころは、for文と組み合わせて複数のリストを同時にループすることです。
names = ["田中", "佐藤", "鈴木"]
ages = [28, 22, 35]
for name, age in zip(names, ages):
print(f"{name}さんは{age}歳です")
実行結果は次の通りです。
田中さんは28歳です
佐藤さんは22歳です
鈴木さんは35歳です
3つ以上のリストを同時にループすることもできます。
names = ["田中", "佐藤", "鈴木"]
ages = [28, 22, 35]
cities = ["東京", "大阪", "福岡"]
for name, age, city in zip(names, ages, cities):
print(f"{name}さん({age}歳・{city}在住)")
実行結果は次の通りです。
田中さん(28歳・東京在住)
佐藤さん(22歳・大阪在住)
鈴木さん(35歳・福岡在住)
zip()で辞書を作る
zip()とdict()を組み合わせると、2つのリストから辞書(キーと値のペアを持つデータ構造)を簡単に作れます。
キー用のリストと値用のリストをzip()でまとめてからdict()に渡すだけです。
keys = ["name", "age", "city"]
values = ["田中", 28, "東京"]
user = dict(zip(keys, values))
print(user)
実行結果は次の通りです。
{'name': '田中', 'age': 28, 'city': '東京'}
CSVの1行目をヘッダー、2行目以降をデータとして扱うようなケースで、このパターンはよく使います。
よくあるつまずきポイント・エラー対処
リストの長さが違うと短い方に合わせられて気づかない
これは筆者が実際にデータ処理のスクリプトで遭遇したつまずきです。
zip()は、渡したリストの中で一番短いリストの長さに合わせて処理を打ち切ります。
エラーにならずに黙って処理が終わるため、データが欠けていることに気づきにくいのが厄介な点です。
❌ Before(データが欠けているのに気づかない書き方)
names = ["田中", "佐藤", "鈴木", "高橋"]
ages = [28, 22, 35]
for name, age in zip(names, ages):
print(f"{name}さんは{age}歳です")
実行結果は次の通りです。
田中さんは28歳です
佐藤さんは22歳です
鈴木さんは35歳です
namesには4人分あるのに、agesが3人分しかないため、「高橋さん」の行がエラーもなく消えてしまいました。
筆者はこの仕様を知らず、なぜかデータが1件足りないと数十分悩んだことがあります。
✅ After(長さの違いに気づける書き方)
長さが揃っているかを事前にチェックするか、itertools.zip_longest()を使って不足分を明示するのが安全です。
names = ["田中", "佐藤", "鈴木", "高橋"]
ages = [28, 22, 35]
if len(names) != len(ages):
print("警告: リストの長さが一致していません")
from itertools import zip_longest
for name, age in zip_longest(names, ages, fillvalue="不明"):
print(f"{name}さんは{age}歳です")
実行結果は次の通りです。
警告: リストの長さが一致していません
田中さんは28歳です
佐藤さんは22歳です
鈴木さんは35歳です
高橋さんは不明歳です
zip_longest()を使えば、不足している要素をfillvalueで指定した値に置き換えてくれるため、データ欠落に気づきやすくなります。
まとめ
この記事のポイント
zip()は複数のイテラブルの要素を組にしてまとめる関数for文と組み合わせると、複数リストを同時にループできるdict(zip(keys, values))で2つのリストから辞書を作れるzip()は最も短いリストに合わせて処理を打ち切るため、長さが違うとデータが欠けることがある- 長さの違いに気づきたい場合は
itertools.zip_longest()を使う
次に読むべき記事
- enumerate()でインデックス付きループを書く
- collections.defaultdictで初期値付き辞書を扱う
- 辞書内包表記・セット内包表記の書き方
タグ: Python, 中級者向け, 基本文法