for文

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

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

Pythonにおけるzipを用いたfor文の使い方について解説します。

for文におけるzipの基本的な使い方

Pythonの繰り返し(ループ)処理ではfor文を使用します。Pythonにおけるfor文の基本的な使い方は「for文の基本的な使い方」にまとめていますので興味があれば参考にしてください。

Pythonのfor文では、リスト、辞書、集合等のイテラブル(iterable)なオブジェクトから要素を取り出して処理をします。この際、複数のオブジェクトを一緒に処理したくなる場合があります。

Pythonにて複数のイテラブルなオブジェクトをまとめてfor文の繰り返し処理で使用したい場合には、zipを使用することで実現できます。

本記事では、zipの基本的な使い方についてリストを使った例を用いて説明します。なお、zipは複数のイテラブルなオブジェクトをまとめて処理するものですが、基本が分かりやすいようにzipでよく使われるだろうリストを使って説明します。

zipの基本的な使い方

zipで複数リストをまとめてfor文で実行する方法

zipを使って、複数リストをまとめてfor文による繰り返し(ループ)処理を実行する場合は、以下例のzip(data1, data2)のように複数のリストを引数に渡してinに指定することでそれぞれのリストから順にデータを取り出します。

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

上記例では、指定したdata1の値がdt1へ、data2の値がdt2へ順に入ってきます。このように複数リストをまとめてfor文の繰り返し(ループ)処理で使用することができます。

タプル(tuple)で取得してfor文を実行する方法

zipの返却値としては、タプル(tuple)が返却されています。上記で見てきた基本的な使い方では、返却値のタプルをdt1とdt2にアンパック代入して使用しているわけです。

そのため、zipを使ったfor文の実行では、以下のようにタプルとして要素を受け取って処理をすることも可能です。

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の値となります。

Note

zipの公式ドキュメントはこちらを参照してください。

要素数が異なる場合の処理

上記ではzipの使い方を紹介しましたが、zipで扱いたい対象の要素数が異なる場合もよくあるかと思います。そのような場合の挙動等について説明します。

zipは少ない要素数のリストにあわせて処理が実行される

zipにおいて、要素数が異なるリストを扱う場合には、「少ない要素数のリストにあわせて処理され、要素数の多い方のリストの残りのデータは無視される」という動作となります。

以下の例で見てみましょう。

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

上記例では、data1の方がdata2よりも要素数が多くなっています。

このような場合、要素数の少ないdata2の要素数にあわせてfor文が実行されるので60, 70, 80, 90, 100というdata1の残りデータは無視されます。要素が多い方にあわせたい場合の処理は次で紹介します。

要素数が多い方にあわせて足りない部分を補完して処理する方法(itertools.zip_longest)

リストの要素が異なる場合に、要素数の多い方にあわせて処理したい場合があります。

このような要素数が多い方のリストにあわせて処理をしたい場合は、itertoolsパッケージのzip_longestを使用します。

以下の例で使い方を見てみましょう。itertoolsは、以下のようにimportして使用してください。

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では、要素数が少ない方のリストの方で”None”が補完されて動作します。

itertools.zip_logestで任意の指定値で補完したい場合(fillvalue)

itertools.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”が補完されていることが分かります。

Note

itertools.zip_longestの公式ドキュメントはこちらを参照してください。

まとめ

Pythonにおけるzipを用いたfor文の使い方について解説しました。

zipは、複数のイテラブルなオブジェクトをまとめてfor文の繰り返し(ループ)処理で使いたいときに使用することができます。本記事では分かりやすいようにリストを使った例で説明をしています。

zipでは、値をそれぞれ取得して使う場合とタプル(tuple)として取得して使う方法があります。また、対象の要素数が異なる場合には少ない要素数に揃えて実行されます。要素数が多い場合には、itertoolsパッケージのzip_longestを使用できることも紹介しました。

複数のイテラブルなオブジェクトをまとめて処理したい場合には、zipをうまく使って対応するようにしてもらえればと思います。