- Python
Python zip・enumerateの使い方|for同時ループのコピペ例集
zip は複数のリストを同時にループする関数、enumerate は要素と一緒に番号(インデックス)を取り出す関数です。 どちらも for 文と組み合わせて使い、for i in range(len(xs)) と書いていた処理を、短く読みやすい形にできます。
この記事では、コピペで使える例を早見表にまとめ、すべてに実行結果を付けました(Python 3.14.7 で実行)。番号を1から始める enumerate(start=1)、番号付きの同時ループ enumerate(zip())、辞書を作る dict(zip())、転置と分解の zip(*)、長さが違うときの zip_longest と strict=True(Python 3.10 以降)まで扱います。長さが違うリストを渡すと余りが黙って切り捨てられる動きも実際に再現し、検出の方法を確かめます。
zip・enumerateの早見表
入力データは次の3つです。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
teams = ["A", "B", "A"]
| やりたいこと | コード | 実行結果 |
|---|---|---|
| 番号と要素を同時に取る | for i, n in enumerate(names): |
0 佐藤/1 鈴木/2 高橋 |
| 番号を1から始める | for i, n in enumerate(names, start=1): |
1 佐藤/2 鈴木/3 高橋 |
| 2つのリストを同時にループ | for n, s in zip(names, scores): |
佐藤 82/鈴木 95/高橋 70 |
| 3つ以上を同時にループ | for n, s, t in zip(names, scores, teams): |
佐藤 82 A … |
| 番号付きで同時にループ | for i, (n, s) in enumerate(zip(names, scores), start=1): |
1 佐藤 82 … |
| 2つのリストから辞書を作る | dict(zip(names, scores)) |
{'佐藤': 82, '鈴木': 95, '高橋': 70} |
| 要素→番号の辞書を作る | {n: i for i, n in enumerate(names)} |
{'佐藤': 0, '鈴木': 1, '高橋': 2} |
| ペアのリストを2つに分解 | ns, ss = zip(*pairs) |
('佐藤', '鈴木', '高橋') (82, 95, 70) |
| 行と列を入れ替える(転置) | list(zip(*matrix)) |
[(1, 4), (2, 5), (3, 6)] |
| 長いほうに合わせる | zip_longest(a, b, fillvalue="-") |
[(1, 'a'), (2, 'b'), (3, '-'), (4, '-')] |
| 長さ違いをエラーで検出 | zip(a, b, strict=True) |
ValueError(3.10 以降) |
| 隣り合う要素をペアにする | pairwise(temps) |
[(12, 15), (15, 14), (14, 20)](3.10 以降) |
| ペアのリストにする | list(zip(names, scores)) |
[('佐藤', 82), ('鈴木', 95), ('高橋', 70)] |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python zip・enumerateの使い方|for同時ループのコピペ例集」
enumerateの使い方
番号と要素を同時に取り出す
enumerate(イテラブル) は、(番号, 要素) のタプルを順に返します。 for の変数を2つ書くと、番号と要素に分けて受け取れます。
names = ["佐藤", "鈴木", "高橋"]
for i, name in enumerate(names):
print(i, name)
0 佐藤
1 鈴木
2 高橋
番号を1から始める(start)
第2引数 start に開始番号を渡します。 画面に「1件目、2件目」と表示したいときに便利です。
for i, name in enumerate(names, start=1):
print(i, name)
print(list(enumerate(names, 1))) # start= は省略して書ける
print(list(enumerate("abc", start=10))) # 文字列にも使える
1 佐藤
2 鈴木
3 高橋
[(1, '佐藤'), (2, '鈴木'), (3, '高橋')]
[(10, 'a'), (11, 'b'), (12, 'c')]
start が変えるのは「数え始めの番号」だけで、要素を途中から取り出すわけではありません。start=1 でも1つ目の要素から順に返ります。リストの添字として使うなら start を付けない(0始まり)ほうが安全です。
start には整数を渡します。文字列を渡すと次のエラーになります。
enumerate(names, "1")
TypeError: 'str' object cannot be interpreted as an integer
enumerateのよくある使い方
names = ["佐藤", "鈴木", "高橋"]
# 進み具合を表示する
for i, name in enumerate(names, start=1):
print(f"{i}/{len(names)} {name}")
# 条件に合う要素の位置を集める
print([i for i, v in enumerate([5, 0, 7, 0]) if v == 0])
# 番号をキーにした辞書/要素から番号を引く辞書
print(dict(enumerate(names)))
print({n: i for i, n in enumerate(names)})
# ループしながら元のリストを書き換える
for i, name in enumerate(names):
if name == "鈴木":
names[i] = "鈴木(更新)"
print(names)
1/3 佐藤
2/3 鈴木
3/3 高橋
[1, 3]
{0: '佐藤', 1: '鈴木', 2: '高橋'}
{'佐藤': 0, '鈴木': 1, '高橋': 2}
['佐藤', '鈴木(更新)', '高橋']
リストの中身を書き換えたいときは、番号 i を使って names[i] = ... と代入します。 ループ変数の name に代入しても、元のリストは変わりません。
ファイルの行番号を付ける使い方も定番です。
lines = ["a\n", "b\n"] # open() で開いたファイルでも同じ書き方
for no, line in enumerate(lines, start=1):
print(no, line.rstrip())
1 a
2 b
逆順に番号付きで回したいときは、いったんリストにしてから reversed をかけます。
for i, name in reversed(list(enumerate(["佐藤", "鈴木", "高橋"]))):
print(i, name)
2 高橋
1 鈴木
0 佐藤
zipの使い方
2つ以上のリストを同時にループする
zip(a, b, ...) は、各リストの同じ位置の要素をタプルにまとめて順に返します。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
teams = ["A", "B", "A"]
for name, score in zip(names, scores):
print(name, score)
for name, score, team in zip(names, scores, teams):
print(name, score, team)
佐藤 82
鈴木 95
高橋 70
佐藤 82 A
鈴木 95 B
高橋 70 A
渡せるのはリストだけではありません。文字列、タプル、range、辞書、ジェネレータなど、for で回せるもの(イテラブル)なら何でも組み合わせられます。
print(list(zip("abc", [1, 2, 3], (True, False, True))))
print(list(zip(range(3), "abc")))
[('a', 1, True), ('b', 2, False), ('c', 3, True)]
[(0, 'a'), (1, 'b'), (2, 'c')]
zipは「同じ位置どうし」、二重ループは「全組み合わせ」
混同しやすいので並べて確認します。
names = ["佐藤", "鈴木"]
items = ["机", "椅子"]
print(list(zip(names, items))) # 同じ位置どうし
print([(n, i) for n in names for i in items]) # 全組み合わせ
[('佐藤', '机'), ('鈴木', '椅子')]
[('佐藤', '机'), ('佐藤', '椅子'), ('鈴木', '机'), ('鈴木', '椅子')]
zip は2件、二重ループは 2×2=4件です。全組み合わせがほしいときは、二重ループか itertools.product を使います。
zipを使った集計・絞り込み・並べ替え
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
print([n for n, s in zip(names, scores) if s >= 80]) # 条件に合う名前
print(sum(p * q for p, q in zip([100, 250], [3, 2]))) # 単価×数量の合計
print(sorted(zip(scores, names), reverse=True)) # 点数の高い順
print(max(zip(scores, names))) # 最高点とその名前
['佐藤', '鈴木']
800
[(95, '鈴木'), (82, '佐藤'), (70, '高橋')]
(95, '鈴木')
タプルは左の要素から比べられるので、比べたい値を先頭にして zip すると、そのまま並べ替えや最大値の取り出しに使えます。
enumerateとzipを組み合わせる
番号付きで同時ループする
enumerate(zip(...)) と重ね、受け取る側を i, (a, b) と丸かっこでくくります。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
for i, (name, score) in enumerate(zip(names, scores), start=1):
print(f"{i}番 {name} {score}点")
1番 佐藤 82点
2番 鈴木 95点
3番 高橋 70点
かっこを忘れたときのエラー
for i, name, score in enumerate(zip(names, scores)):
pass
ValueError: not enough values to unpack (expected 3, got 2)
enumerate が返すのは (番号, (名前, 点数)) という 2要素のタプルです。3つの変数で受けようとすると数が合いません。i, (name, score) と、中のタプルの形に合わせてかっこを付けると解決します。
かっこを付けずに2つの変数で受けると、2つ目にタプルがそのまま入ります。
for i, pair in enumerate(zip(["佐藤", "鈴木"], ["机", "椅子"])):
print(i, pair)
0 ('佐藤', '机')
1 ('鈴木', '椅子')
辞書と組み合わせる
d = {"a": 1, "b": 2}
for i, (key, value) in enumerate(d.items(), start=1):
print(i, key, value)
1 a 1
2 b 2
d.items() も (キー, 値) のタプルを返すので、同じ形で受け取れます。
dict(zip())で辞書を作る
キーのリストと値のリストを zip でペアにし、dict() に渡すと辞書になります。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
print(dict(zip(names, scores)))
print({n: s for n, s in zip(names, scores) if s >= 80}) # 条件付きは辞書内包表記
{'佐藤': 82, '鈴木': 95, '高橋': 70}
{'佐藤': 82, '鈴木': 95}
見出し行とデータ行から「辞書のリスト」を作る、表形式データの定番の形です。
rows = [["id", "name"], [1, "机"], [2, "椅子"]]
header, *body = rows
print([dict(zip(header, r)) for r in body])
[{'id': 1, 'name': '机'}, {'id': 2, 'name': '椅子'}]
キーと値を入れ替えた辞書も作れます。
old = {"a": 1, "b": 2}
print(dict(zip(old.values(), old.keys())))
{1: 'a', 2: 'b'}
気を付ける点が2つあります。
| 状況 | 起きること | 実行結果 |
|---|---|---|
| キーが重複している | 後の値で上書きされる | dict(zip(["id", "name", "id"], [1, "机", 2])) → {'id': 2, 'name': '机'} |
| 値のほうが短い | 余ったキーが黙って消える | dict(zip(["id", "name", "qty"], [1, "机"])) → {'id': 1, 'name': '机'} |
2つ目は次の章で詳しく見ます。
zip(*)で転置・分解する
ペアのリストを2つに分ける
zip(*リスト) と * を付けると、リストの中身をばらして zip に渡せます。 zip でまとめたものを元に戻す操作になります。
pairs = [("佐藤", 82), ("鈴木", 95), ("高橋", 70)]
names, scores = zip(*pairs)
print(names, scores)
('佐藤', '鈴木', '高橋') (82, 95, 70)
zip(*pairs) は zip(("佐藤", 82), ("鈴木", 95), ("高橋", 70)) と同じ意味です。結果はタプルなので、リストがほしいときは list(names) で変換します。
行と列を入れ替える(転置)
matrix = [[1, 2, 3], [4, 5, 6]]
print(list(zip(*matrix)))
print([list(row) for row in zip(*matrix)]) # 各行をリストにする
[(1, 4), (2, 5), (3, 6)]
[[1, 4], [2, 5], [3, 6]]
2行3列が3行2列になりました。行ごとのデータを列ごとに取り出したいときに使えます。
行の長さがそろっていないと、いちばん短い行に合わせて切り捨てられます。
from itertools import zip_longest
rows = [[1, 2, 3], [4, 5], [6, 7, 8]]
print(list(zip(*rows)))
print(list(zip_longest(*rows, fillvalue=0)))
[(1, 4, 6), (2, 5, 7)]
[(1, 4, 6), (2, 5, 7), (3, 0, 8)]
3列目が消えました。zip_longest で埋めるか、zip(*rows, strict=True) で長さの違いを検出できます。
n個ずつにまとめる
同じイテレータを複数回 zip に渡すと、n個ずつのかたまりを作れます。
it = iter([1, 2, 3, 4, 5, 6])
print(list(zip(it, it))) # 2個ずつ
it = iter([1, 2, 3, 4, 5, 6])
print(list(zip(it, it, it))) # 3個ずつ
[(1, 2), (3, 4), (5, 6)]
[(1, 2, 3), (4, 5, 6)]
この書き方は、余りが出ると切り捨てられます。Python 3.12 以降は itertools.batched が使え、余りも残ります。
from itertools import batched
print(list(batched(range(7), 3)))
[(0, 1, 2), (3, 4, 5), (6,)]
長さが違うリストをzipするとどうなるか
再現:余りが黙って切り捨てられる
zip は、いちばん短いイテラブルが尽きた時点で止まります。エラーも警告も出ません。
a = [1, 2, 3, 4]
b = ["a", "b"]
print(list(zip(a, b)))
[(1, 'a'), (2, 'b')]
3 と 4 が結果から消えました。備品の ID と名前の対応を作る例で見ると、影響がよく分かります。
ids = [101, 102, 103, 104]
labels = ["机", "椅子", "棚"] # 1件足りない
print(dict(zip(ids, labels)))
{101: '机', 102: '椅子', 103: '棚'}
ID 104 が辞書に入らないまま、処理が最後まで進みます。 データの取り込み漏れに気づくのが後工程になりやすいところです。
strict=Trueで検出する(Python 3.10以降)
zip(..., strict=True) を付けると、長さが違うときに ValueError で知らせてくれます。 Python 3.10 で追加された引数です(PEP 618)。
dict(zip(ids, labels, strict=True))
ValueError: zip() argument 2 is shorter than argument 1
メッセージは、どの引数が長い/短いかまで教えてくれます。実際に出たメッセージの一覧です。
| コード | メッセージ |
|---|---|
zip([1, 2, 3, 4], ["a", "b"], strict=True) |
zip() argument 2 is shorter than argument 1 |
zip(["a", "b"], [1, 2, 3, 4], strict=True) |
zip() argument 2 is longer than argument 1 |
zip(a, a, b, strict=True)(3つ目だけ短い) |
zip() argument 3 is shorter than arguments 1-2 |
長さが同じなら、strict=True を付けても結果は変わりません。
print(list(zip(names, scores, strict=True)))
[('佐藤', 82), ('鈴木', 95), ('高橋', 70)]
strictのエラーは「ループの最後」で出る
知っておくと役立つ性質があります。strict=True のエラーは、短いほうが尽きた時点で初めて出ます。 それまでの要素は処理済みです。
done = []
try:
for i, label in zip(ids, labels, strict=True):
done.append(i) # ここで保存などの処理をしていると…
except ValueError as e:
print(e, done)
zip() argument 2 is shorter than argument 1 [101, 102, 103]
3件ぶんの処理は終わったあとでエラーになりました。「1件でも合わなければ何も処理したくない」ときは、先にリストにしてから処理します。
pairs = list(zip(ids, labels, strict=True)) # ここで長さを検査
for i, label in pairs:
... # 検査を通ったものだけ処理
リストどうしなら、事前に len(ids) == len(labels) を確かめる方法も分かりやすいです。ジェネレータのように長さが分からないものを渡すときは、strict=True が頼りになります。
zip_longestで長いほうに合わせる
足りないところを埋めて最後まで回したいときは、itertools.zip_longest を使います。
from itertools import zip_longest
a = [1, 2, 3, 4]
b = ["a", "b"]
print(list(zip_longest(a, b))) # 既定では None で埋める
print(list(zip_longest(a, b, fillvalue="-"))) # 埋める値を指定
[(1, 'a'), (2, 'b'), (3, None), (4, None)]
[(1, 'a'), (2, 'b'), (3, '-'), (4, '-')]
見出しに対して値が足りない行を、欠けたまま辞書にする例です。
header = ["id", "name", "qty"]
row = [1, "机"]
print(dict(zip(header, row))) # qty が消える
print(dict(zip_longest(header, row))) # qty が None で残る
{'id': 1, 'name': '机'}
{'id': 1, 'name': '机', 'qty': None}
どれを選ぶかの判断表
| 状況 | 選ぶもの | 長さが違うとき |
|---|---|---|
| 長さは必ず同じはず(違えば入力の誤り) | zip(a, b, strict=True) |
ValueError で知らせる |
| 短いほうに合わせてよいと分かっている | zip(a, b) |
余りを切り捨てる |
| 長いほうに合わせ、足りない分は埋めたい | zip_longest(a, b, fillvalue=...) |
既定値で埋める |
無限に続くものと組み合わせる(count() など) |
zip(a, b) |
有限のほうで止まる |
「同じ長さのはず」と考えて書くことが多いなら、strict=True を付けておくと、データのずれに早く気づけます。Python 3.9 以前には strict がないため、その環境では len() の比較で確かめます(3.9 以前での動作は手元では実行しておらず、公式ドキュメントの記載によります)。
range(len())から書き換える
for i in range(len(xs)) は動きますが、番号がほしいなら enumerate、複数のリストを回すなら zip に置き換えると、添字の書き間違いが減り、意図が読み取りやすくなります。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
# 書き換え前
for i in range(len(names)):
print(i, names[i], scores[i])
# 書き換え後
for i, (name, score) in enumerate(zip(names, scores)):
print(i, name, score)
0 佐藤 82
1 鈴木 95
2 高橋 70
0 佐藤 82
1 鈴木 95
2 高橋 70
| 書き換え前 | 書き換え後 | 使う関数 |
|---|---|---|
for i in range(len(xs)): x = xs[i] |
for x in xs: |
なし(そのまま回す) |
for i in range(len(xs)): print(i, xs[i]) |
for i, x in enumerate(xs): |
enumerate |
for i in range(len(xs)): print(i + 1, xs[i]) |
for i, x in enumerate(xs, start=1): |
enumerate の start |
for i in range(len(xs)): f(xs[i], ys[i]) |
for x, y in zip(xs, ys): |
zip |
for i in range(len(xs)): f(i, xs[i], ys[i]) |
for i, (x, y) in enumerate(zip(xs, ys)): |
enumerate と zip |
for i in range(len(xs) - 1): f(xs[i], xs[i + 1]) |
for a, b in pairwise(xs): |
itertools.pairwise |
for i in range(len(xs)): xs[i] = g(xs[i]) |
xs = [g(x) for x in xs] |
内包表記 |
range(len()) が合う場面もあります。番号だけが必要で要素を使わないとき、1つ飛ばしなど番号の進み方を細かく決めたいときは、range のほうが素直です。
速度は同程度
10万要素の2つのリストを足し合わせるループで測りました(Python 3.14.7、timeit で10回×15セットの最小値。数値は環境によって変わります)。
| 書き方 | 1回あたり |
|---|---|
for i in range(len(N)): x = N[i] + M[i] |
2.70 ms |
for a, b in zip(N, M): x = a + b |
2.42 ms |
for a, b in zip(N, M, strict=True): x = a + b |
2.44 ms |
zip のほうがわずかに速く、strict=True を付けても差はほぼありませんでした。速度を理由に strict を外す必要はなさそうです。書き換えの主な利点は、速度よりも読みやすさと添字ミスの防止にあります。
zipとenumerateは1回で使い切る(イテレータ)
zip() と enumerate() が返すのはリストではなく、イテレータ(1回だけ順に取り出せるオブジェクト)です。 2回目に回すと空になります。
names = ["佐藤", "鈴木", "高橋"]
scores = [82, 95, 70]
z = zip(names, scores)
print(z)
print(list(z))
print(list(z)) # 2回目
<zip object at 0x7f85b79a96c0>
[('佐藤', 82), ('鈴木', 95), ('高橋', 70)]
[]
enumerate も同じです。
e = enumerate(names)
print(next(e)) # 1つ取り出す
print(list(e)) # 残り
print(list(e)) # もう空
(0, '佐藤')
[(1, '鈴木'), (2, '高橋')]
[]
何度も使いたい、件数を知りたい、添字で取りたいときは、list() で受けて変数に入れます。
data = list(zip(names, scores))
print(len(data), data[0])
3 ('佐藤', 82)
リストにしないまま len() や添字を使うと、次のエラーになります。
| コード | エラー |
|---|---|
len(zip(names, scores)) |
TypeError: object of type 'zip' has no len() |
zip(names, scores)[0] |
TypeError: 'zip' object is not subscriptable |
渡した側のイテレータも進む
ジェネレータなどのイテレータを zip に渡すと、渡した側も消費されます。
g = (x for x in [1, 2, 3])
print(list(zip(g, "abc")), list(zip(g, "abc")))
[(1, 'a'), (2, 'b'), (3, 'c')] []
2回目は g が尽きているので空です。さらに、長さが違うときは引数の順番によって、余分に1つ取り出されることがあります。
x = iter([1, 2, 3]); y = iter(["a"])
print(list(zip(x, y)), list(x)) # 長いほうが先
x = iter([1, 2, 3]); y = iter(["a"])
print(list(zip(y, x)), list(x)) # 短いほうが先
[(1, 'a')] [3]
[('a', 1)] [2, 3]
zip は左の引数から順に1つずつ取り出します。長い x が先にあると、2 を取り出したあとで y が尽きたと分かるため、2 は使われないまま消えます。残りを後で使いたいイテレータは、短いほうを先に書くか、リストにしてから渡すと確実です。
イテレータである利点もあります。必要な分だけ順に作るので、大きなデータでもメモリを使いすぎません。zip(count(1), names) のように、終わりのない itertools.count と組み合わせても、有限のほうで止まります。
itertools.pairwiseで隣どうしを比べる(3.10以降)
itertools.pairwise(xs) は、隣り合う要素を (1つ目, 2つ目)、(2つ目, 3つ目) … とペアにして返します。 Python 3.10 で追加されました。
from itertools import pairwise
temps = [12, 15, 14, 20]
print(list(pairwise(temps)))
print([b - a for a, b in pairwise(temps)]) # 前との差
print(all(a <= b for a, b in pairwise([1, 2, 2, 5]))) # 昇順に並んでいるか
print(list(pairwise([1])), list(pairwise("ABCD")))
[(12, 15), (15, 14), (14, 20)]
[3, -1, 6]
True
[] [('A', 'B'), ('B', 'C'), ('C', 'D')]
要素が1つ以下のときは空になります。同じことは zip(xs, xs[1:]) でも書けます。
print(list(zip(temps, temps[1:])))
print(list(zip(temps, temps[1:], temps[2:]))) # 3つ組はスライスを増やす
[(12, 15), (15, 14), (14, 20)]
[(12, 15, 14), (15, 14, 20)]
| 書き方 | 使える対象 | 特徴 |
|---|---|---|
pairwise(xs) |
イテラブルなら何でも | コピーを作らない。3.10 以降 |
zip(xs, xs[1:]) |
スライスできるもの(リストなど) | スライスの分だけコピーができる。3つ組にも広げやすい |
番号も一緒にほしいときは、enumerate と組み合わせられます。
for (i, x), (j, y) in pairwise(enumerate([10, 13, 11])):
print(i, j, y - x)
0 1 3
1 2 -2
zip_longest・pairwise・batched 以外の itertools の関数は、当サイトの itertools の記事に一覧でまとめています。
よくあるつまずきと直し方
| 症状・エラー | 原因 | 直し方 |
|---|---|---|
<zip object at 0x...> と表示される |
zip はイテレータを返す | list(zip(...)) で包む |
| 2回目のループで何も出ない | イテレータは1回で使い切る | 先に list() で受ける |
not enough values to unpack (expected 3, got 2) |
enumerate(zip()) の受け取りにかっこがない |
for i, (a, b) in ... |
| 結果の件数が少ない | 長さが違い、短いほうで止まった | strict=True で検出、zip_longest で埋める |
zip() argument 2 is shorter than argument 1 |
strict=True で長さの違いを検出 |
入力データの件数を確認する |
object of type 'zip' has no len() |
イテレータに len() を使った |
list() にしてから |
'str' object cannot be interpreted as an integer |
enumerate の start に文字列 |
整数を渡す |
| 番号が1つずれる | start=1 の番号を添字に使った |
添字用は start なし、表示用だけ start=1 |
| 辞書の件数が減った | キーの重複、または値のリストが短い | キーの重複を確認、strict=True |
よくある質問
Q. zip と enumerate はどう使い分けますか?
A. 番号がほしいときは enumerate、複数のリストを同時に回したいときは zip です。両方ほしいときは for i, (a, b) in enumerate(zip(xs, ys)): と組み合わせます。
Q. zip で長さが違うリストを渡すとエラーになりますか?
A. 既定ではエラーにならず、短いほうに合わせて余りが切り捨てられます。Python 3.10 以降は zip(a, b, strict=True) と書くと ValueError で検出できます。長いほうに合わせたいときは itertools.zip_longest を使います。
Q. enumerate の番号を1から始めるには?
A. enumerate(xs, start=1) と書きます。start は数え始めの番号を変えるだけで、要素は1つ目から順に返ります。
Q. zip した結果を元の2つのリストに戻せますか?
A. a, b = zip(*pairs) で戻せます。結果はタプルになるので、リストがほしいときは list(a) で変換します。pairs が空のときは左辺の変数の数と合わずエラーになるため、空の可能性がある場合は先に件数を確かめます。
まとめ
enumerate(xs)は(番号, 要素)、zip(a, b)は(aの要素, bの要素)を順に返す。番号を1から始めるにはstart=1- 番号付きの同時ループは
for i, (a, b) in enumerate(zip(xs, ys)):。受け取る側のかっこを忘れるとnot enough values to unpackになる dict(zip(keys, values))で辞書、zip(*pairs)で分解と転置ができる- zip は短いほうで止まり、余りは黙って切り捨てられる。同じ長さのはずなら
strict=True(3.10 以降)、埋めたいならzip_longest strict=Trueのエラーは短いほうが尽きた時点で出る。途中まで処理したくないときは、先にlist()にする- zip と enumerate はイテレータで、1回回すと空になる。何度も使う、
len()を取る、添字で取るならlist()で受ける range(len(xs))は enumerate/zip/pairwise に書き換えられる。速度は同程度で、読みやすさと添字ミスの防止が利点
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python zip・enumerateの使い方|for同時ループのコピペ例集」
株式会社RJCでは、Pythonのzipやenumerateを使ったループの書き方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。