[Python] zip()の使い方(複数のリストの要素を組合わせる)

 いくつかのリストの要素を組み合わせてforループを回したい場合は、zip()を使うと便利です。
 zip()関数はPythonの標準の組み込み関数で、複数のリストの同一インデックスの要素を組み合わせて新しいイテレータを生成します。
 本記事では、この関数の使い方と併せて、イテレータをunzip(分解)して元のイテラブルに戻す方法についてもまとめます。
 最後に、これらの応用例として2次元配列の転置をする方法についても記載しています。

確認した環境

  • OS: Ubuntu 16.04LTS
  • Python 3.7.2@Anaconda

zip()の使い方

zip()関数は引数として与えられた複数のイテラブル(リスト、タプル、文字列等)を組み合わせて、新しいイテラブルを作ります。基本的な使い方は以下です。

zip(*iterables)

戻り値はzipオブジェクトで、それぞれのiterableの同じインデックスの要素が組み合わされ、タプルのイテレータとして返ります。
具体的な例を以下に示します。

>>> A = ['a', 'b', 'c']
>>> B = ['1', '2', '3']

# 返却値はzipオブジェクト
>>> zip(A, B)
<zip object at 0x7f1a06acfdc8>

# リストAとリストBの同じインデックスの要素が組み合わせれ、タプルで返されます
>>> list(zip(A, B))
[('a', '1'), ('b', '2'), ('c', '3')]

# リストは3つ以上でも可能です
>>> C = ['x', 'y', 'z']
>>> list(zip(A, B, C))
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z')]

入力のイテラブルの長さが異なる場合は、短い方に合わせます。

#長さの異なるリストの組み合わせの場合は、短い方に合わせる
>>> X = ['v', 'w', 'x', 'y', 'z']
>>> list(zip(A, X))
[('a', 'v'), ('b', 'w'), ('c', 'x')]

イテラブルのunzip(分解)について

引数に(*)をつけると、unzip(元のイテラブルに分解)できます。

>>> d = [(1, 'a'), (2, 'b'), (3, 'c')]
>>> a1, b1 = zip(*d)
>>> a1
(1, 2, 3) #戻り値はタプル
>>> b1
('a', 'b', 'c') #戻り値はタプル

#リストで出力
>>> list(zip(*d))
[(1, 2, 3), ('a', 'b', 'c')]

#タプルで出力
>>> tuple(zip(*d))
((1, 2, 3), ('a', 'b', 'c'))

#辞書の場合はエラー
>>> dict(zip(*d))
Traceback (most recent call last):
  File "", line 1, in 
ValueError: dictionary update sequence element #0 has length 3; 2 is required

<参考文献> Python公式リファレンス: 組み込み関数 zip

応用例(2次元配列の転置)

これを応用すると、list型の2次元配列の転置もできます。
以下の例では、zip()関数はタプルのイテレータを返すので、map関数でlist型に変換しています。

>>> import pprint
>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

#元の配列
>>> pprint.pprint(x, width=20)
[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]

#転置後の配列
>>> x_ = list(map(list, zip(*x)))
>>> pprint.pprint(x_, width=20)
[[1, 4, 7],
 [2, 5, 8],
 [3, 6, 9]]

まとめ

今回は、複数のリストの同一のインデックスの要素を組み合わせて新しいイテレータを生成するzip関数についてまとめました。また、タプルを要素としたリストをunzip(分解)して元のリストに戻す方法についても示しました。

Learn more...

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!

[Sponsor link]