Python の zip()関数
Python およびすべてのプログラミング言語では、for
および while
ループを使用して配列を反復処理できます。単一の配列を反復処理するのは非常に簡単です。ただし、複数の配列を一緒に反復処理する場合、状況は複雑になり始めます。すべてのアレイのサイズが同じである場合、それは簡単な作業です。ただし、配列のサイズが異なる場合は、エラーや例外を回避するために、最小の配列の長さのみを考慮する必要があります。
Python を使用すると、このタスクがはるかに簡単になります。さまざまなサイズの配列を反復処理するためのロジックを手動で作成する代わりに、Python が提供する組み込みのユーティリティ、より正確には関数を使用できます。この関数は zip()
関数です。
この記事では、zip()
関数とその使用方法を紹介します。
Python の zip()
関数
zip()
関数は、リスト、文字列、タプルなどの反復可能なオブジェクトを引数として受け入れ、単一の反復可能オブジェクトを返します。
返される iterable オブジェクトは、最小の iterable の長さを持ちます。たとえば、サイズ 5
と 10
の 2つのリストが zip()
関数に提供されている場合、返される反復可能オブジェクトの長さは 5
になります。これは、2 番目のリストの最初の 5
要素のみが反復可能オブジェクトの一部になることを意味します。空の iterable または iterable オブジェクトがこの関数に指定されていない場合、空の iterable も返します。
理論が完成したので、この関数の使用方法を見てみましょう。その使用法を理解するには、次の例を参照してください。
反復可能なオブジェクトはありません
次の Python コードでは、反復可能なオブジェクトは zip()
関数に渡されません。
result = zip()
for x in result:
print(x)
上記のコードを実行しても、コンソールには何も出力されません。同じ理由は単純です。反復可能なオブジェクトが提供されていない場合、反復するものは何もありません。したがって、空の反復可能オブジェクトが返されます。
同じ長さの反復可能なオブジェクト
次の Python コードでは、整数のタプル、浮動小数点値のリスト、クラスオブジェクトのリスト、および同じ長さの文字列が zip()
関数に渡されます。
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
for x in result:
print(x)
出力:
(11, 1.1, Number(1), 'H')
(22, 2.2, Number(23), 'e')
(33, 3.3, Number(44.44), 'l')
(44, 4.4, Number(0), 'l')
(55, 5.5, Number(-9), 'o')
ご覧のとおり、zip()
関数は、すべての反復可能なオブジェクトの値をタプルにまとめて格納します。タプル内の値の順序は、反復可能なオブジェクトが zip()
関数に提供された順序と同じです。
簡単にアクセスできるように、for
ループ内でこれらの値を分解または解凍できます。同じことについては、次のコードを参照してください。
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
for p, q, r, s in result:
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
出力:
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
A: 44
B: 4.4
C: Number(0)
D: l
A: 55
B: 5.5
C: Number(-9)
D: o
for
ループを使用する代わりに、while
ループを使用して反復可能なオブジェクトを反復可能にすることもできます。while
ループでは、next()
関数と try-except
ブロックの 2つが追加で必要になります。next()
関数は、zip()
関数によって返される反復可能オブジェクトから値を取得するために使用され、try-except
ブロックは、反復を停止するために使用されます。同じことについては、次の Python コードを参照してください。
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
while True:
try:
p, q, r, s = next(result)
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
except StopIteration:
break
出力:
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
A: 44
B: 4.4
C: Number(0)
D: l
A: 55
B: 5.5
C: Number(-9)
D: o
イテレータ内で使用可能な値がない場合、StopIteration
例外が発生します。try-except
ブロックを使用して、この例外をキャッチし、無限の while
ループを終了します。
さまざまな長さの反復可能なオブジェクト
次の Python コードでは、整数のタプル、浮動小数点値のリスト、クラスオブジェクトのリスト、およびさまざまな長さの文字列が zip()
関数に渡されます。
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33)
b = [1.1, 2.2, 3.3, 4.4]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "HelloWorld"
result = zip(a, b, c, d)
for p, q, r, s in result:
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
出力:
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
すべての反復可能なオブジェクトの長さは異なります。最初の反復可能なオブジェクトまたは整数のタプルの長さは最小で、3
です。したがって、出力はすべての反復可能なオブジェクトからの最初の 3
値のみを出力します。
辞書の作成
zip()
関数を使用して、キーと値のペアの辞書を作成できます。アイデアは、同じ長さの 2つの配列のイテレーターを作成し、キーとそれぞれの値を含み、返された反復可能オブジェクトを反復しながら、ディクショナリ内でそれらを相互にマッピングすることです。同じことについては、次のコードを参照してください。
import json
a = ["W", "O", "R", "L", "D"]
b = [1.1, True, "Hello", None, 5]
result = zip(a, b)
mapping = {x: y for x, y in result}
print(json.dumps(mapping, indent=4))
出力:
{
"W": 1.1,
"O": true,
"R": "Hello",
"L": null,
"D": 5
}
上記のコードは、辞書の出力を美化するために json
モジュールのみを使用しています。それを使用することは完全にオプションであることに注意してください。
zip()
関数と enumerate()
関数の使用
enumerate()
関数は、反復可能なオブジェクトを反復処理しながら、インデックスと値を同時に取得するために使用されます。zip()
関数はイテレータを返すため、2つの関数をまとめて、インデックスと値にアクセスできます。同じことについては、次の Python コードを参照してください。
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33)
b = [1.1, 2.2, 3.3, 4.4]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "HelloWorld"
result = zip(a, b, c, d)
for i, (p, q, r, s) in enumerate(result):
print(f"A{i + 1}:", p)
print(f"B{i + 1}:", q)
print(f"C{i + 1}:", r)
print(f"D{i + 1}:", s)
出力:
A1: 11
B1: 1.1
C1: Number(1)
D1: H
A2: 22
B2: 2.2
C2: Number(23)
D2: e
A3: 33
B3: 3.3
C3: Number(44.44)
D3: l
上記の Python コードでは、for
ループ内で、i, (p, q, r, s)
enumerate() 関数によって返された値を解凍し、
(p, q, r, s) は zip()
関数によって返された値を解凍します。
enumerate()
関数によって返される値は、次の形式です。
(0, (11, 1.1, Number(1), "H"))
(1, (22, 2.2, Number(23), "e"))
(2, (33, 3.3, Number(44.44), "l"))
i, (p, q, r, s)
がすべての値を解凍するために使用された理由を明らかにします。