概要
- リストの要素数を取得して処理を行う場合に、
zip
関数だと短い方の要素数に合わせてペアが作成されてしまい、ちょっと詰まったフェーズがあったので備忘録として残します。
短い方の要素数に合わせて処理する場合
abc_company_codes = ["a", "b", "c"]
xyz_company_codes = ["x"]
for abc_code, xyz_code in zip(abc_company_codes, xyz_company_codes):
print("abc_code:", abc_code)
print("xyz_code:", xyz_code)
# 出力結果
# abc_code: a
# xyz_code: x
-
zip
関数は、複数のイテラブル(リストやタプルなど)をまとめて処理するための関数。 - 大事なポイントは、要素数が異なるリストであっても、短い方の要素数に合わせてペアが作成される、と言うこと。「短い方」と言うことを知らないと詰まってしまう。
- 出力結果を見てわかるように、短い方の
xyz_company_codes
に合わせて作成されるので、abc_company_codes
のb
とc
は出力されません。abc_code
とxyz_code
は1つずつのペアで取得されるからです。 - 要素ごとに対応関係がある場合には便利です。
長い方の要素数に合わせて処理する場合
abc_company_codes = ["a", "b", "c"]
xyz_company_codes = ["x"]
max_len = max(len(abc_company_codes), len(xyz_company_codes))
for i in range(max_len):
abc_code = abc_company_codes[i] if i < len(abc_company_codes) else None
xyz_code = xyz_company_codes[i] if i < len(xyz_company_codes) else None
print("abc_code:", abc_code)
print("xyz_code:", xyz_code)
# 出力結果
# abc_code: a
# xyz_code: x
# abc_code: b
# xyz_code: None
# abc_code: c
# xyz_code: None
- 上記の場合、長い方の要素数を
max_len
として設定します。 - 要素数が異なるリストでも、要素のペアを作成せずに、それぞれのリストの要素を個別に処理します。ただし、要素数が足りない場合は上記の出力結果のように
None
となります。ここは、else None
のところで調整できます。 - 対応関係がない場合に便利ですね。
- ただ、、、もっと楽な記載方法ないのか?と思ったら、ちゃんとあった。以下のように簡潔に記載できます。
import itertools
abc_company_codes = ["a", "b", "c"]
xyz_company_codes = ["x"]
for abc_code, xyz_code in itertools.zip_longest(abc_company_codes, xyz_company_codes):
print("abc_code:", abc_code)
print("xyz_code:", xyz_code)
# 出力結果
# abc_code: a
# xyz_code: x
# abc_code: b
# xyz_code: None
# abc_code: c
# xyz_code: None
-
itertools.zip_longest
関数を使用すると、要素数の異なる複数のイテラブルをまとめて処理することができます。 - 異なる要素数の場合、欠損した部分は
None
で埋められますが、fillvalue
引数を使用して欠損部分の値をカスタマイズすることもできるんですね。
import itertools
abc_company_codes = ["a", "b", "c"]
xyz_company_codes = ["x"]
for abc_code, xyz_code in itertools.zip_longest(abc_company_codes, xyz_company_codes, fillvalue="N/A"):
print(abc_code)
print(xyz_code)
# 出力結果
# a
# x
# b
# N/A
# c
# N/A