【Python】zipを用いたfor文の使い方 ~複数のリストをまとめて処理~

Pythonにおけるzipを用いたfor文の使い方について解説します。
目次
for文におけるzipの基本的な使い方
Pythonの繰り返し処理にはfor文を使用します。for文の基本については「for文の基本的な使い方」を参照してください。
Pythonのfor文では、リストや辞書などのイテラブルなオブジェクトを処理します。複数のオブジェクトを同時に処理するにはzipが便利です。
この記事では、zipを用いたfor文の使い方について紹介します。
zipの基本的な使い方
以降ではリストを対象としてzipの基本的な使い方を紹介します。以降の例ではリストを使用しましたが、他のイテラブルなオブジェクトにも適用可能です。
zipで複数リストをまとめてfor文で実行する方法
以下にzipを使ったfor文の例を示します。
data1 = [10, 20, 30, 40, 50]
data2 = ["A", "B", "C", "D", "E"]
# zipで複数リストをまとめて処理する
for dt1, dt2 in zip(data1, data2):
print(f"dt1: {dt1}, dt2: {dt2}")【実行結果】 dt1: 10, dt2: A dt1: 20, dt2: B dt1: 30, dt2: C dt1: 40, dt2: D dt1: 50, dt2: E
zip(data1, data2)のように複数リストを渡してfor文で使用します。各ループで、data1の要素がdt1に、data2の要素がdt2に順に格納されます。
タプル(tuple)で取得してfor文を実行する方法
zipを使うとデータはタプルとして取得されます。for文で1つの変数に受け取るとタプルとして扱えます。
data1 = [10, 20, 30, 40, 50]
data2 = ["A", "B", "C", "D", "E"]
# zipで複数リストをまとめて処理する (タプルで取得する)
for tpl in zip(data1, data2):
print(f"dt1: {tpl[0]}, dt2: {tpl[1]}")【実行結果】 dt1: 10, dt2: A dt1: 20, dt2: B dt1: 30, dt2: C dt1: 40, dt2: D dt1: 50, dt2: E
上記例では、タプルの0番目がdata1、1番目がdata2の値です。
要素数が異なる場合の処理
ここまでzipの使い方を紹介しましたが、要素数が異なる場合の処理についても説明します。
zipは少ない要素数のリストにあわせて処理される
zipでは、要素数が異なるリストを扱う場合、少ない方にあわせて処理されて、多い方の残りは無視されます。
以下のようにdata1の方がdata2よりも要素が多い場合の例で見てみましょう。
data1 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
data2 = ["A", "B", "C", "D", "E"]
# 要素の長さが異なる場合(少ない要素数にあわせて実行される)
for dt1, dt2 in zip(data1, data2):
print(f"dt1: {dt1}, dt2: {dt2}")【実行結果】 dt1: 10, dt2: A dt1: 20, dt2: B dt1: 30, dt2: C dt1: 40, dt2: D dt1: 50, dt2: E
上記ような場合、要素数の少ないdata2の要素数にあわせてfor文が実行されるのでdata1のデータのうち「60, 70, 80, 90, 100」は無視されます。
要素数が多い方にあわせて足りない部分を補完して処理する方法(itertools.zip_longest)
上記までで紹介した通り、zipでは要素の少ない方にあわせて処理されるため、要素数が多い方の残りの部分は無視されてしまいました。しかし、要素数の多い方のデータもすべて含めて扱いたい場合もあります。
このように要素数が多い方のリストに合わせて処理をしたい場合には、itertoolsパッケージのzip_longestを使用することができます。itertoolsは、イテレーションに関する様々なユーティリティを提供し、かつ効率のよく処理をしてくれるライブラリです。
以下の例でzip_longestの使い方を見てみましょう。
import itertools
data1 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
data2 = ["A", "B", "C", "D", "E"]
# itertools.zip_longestを用いて、不足分をNoneで補完する
for dt1, dt2 in itertools.zip_longest(data1, data2):
print(f"dt1: {dt1}, dt2: {dt2}")【実行結果】 dt1: 10, dt2: A dt1: 20, dt2: B dt1: 30, dt2: C dt1: 40, dt2: D dt1: 50, dt2: E dt1: 60, dt2: None dt1: 70, dt2: None dt1: 80, dt2: None dt1: 90, dt2: None dt1: 100, dt2: None
zip_longestを使用するには、itertoolsをインポートが必要です。デフォルトでは、足りない部分はNoneで補完されます。
itertools.zip_logestで任意の指定値で補完したい場合(fillvalue)
zip_longestは、デフォルトでは少ない方の要素をNoneで補完しますが、fillvalue引数で任意の値を指定できます。
import itertools
data1 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
data2 = ["A", "B", "C", "D", "E"]
# itertools.zip_longestで、補完する値を指定する
for dt1, dt2 in itertools.zip_longest(data1, data2, fillvalue="Z"):
print(f"dt1: {dt1}, dt2: {dt2}")【実行結果】 dt1: 10, dt2: A dt1: 20, dt2: B dt1: 30, dt2: C dt1: 40, dt2: D dt1: 50, dt2: E dt1: 60, dt2: Z dt1: 70, dt2: Z dt1: 80, dt2: Z dt1: 90, dt2: Z dt1: 100, dt2: Z
上記例では、補完にfillvalue="Z"を指定しているため、data2のリストで不足する部分には、Zが補完されていることが分かります。
まとめ
Pythonにおけるzipを用いたfor文の使い方について解説しました。
zipは複数のイテラブルなオブジェクトをfor文で同時に処理するために使用します。例で紹介したリスト以外のイテラブルにも使えるので、柔軟に利用できます。
zipでは、値を直接取得する方法とタプルとして取得する方法があります。また、zipは要素数が異なる場合は少ない方にあわせて処理されますが、itertoolsのzip_longestを使うことで不足する部分を補完して処理することもできます。
for文での処理では、zipは非常によく使う方法ですので、うまく使いこなせるようになってもらいたいと思います。
上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。




