Python で for 文を使うと、さまざまなイテラブルから 1 つずつ順番に要素を取り出すことができます。そして、時には、 for ループで、取り出す要素のindex(インデックス番号)も同時に参照したい場合が出てくるでしょう。
ここでは、その場合に役立つ方法をまとめて解説します。
ぜひ、参考にして頂ければ幸いです。
1. len 関数でインデックスと要素を取り出す
まずは、list 関数を使う方法を解説します。
結論からお伝えすると、この方法は、コードの見た目もわかりにくいですし、プログラムの処理効率も良くないので使うことはありません。この後に解説する enumerate 関数を使う方法が一般的です。
それでも、for in 文への理解や、コーディングそのものに対する理解を深めるために役立ちますので、念のため解説しておきます。
先に「Python の for in range 文の重要知識と使い方まとめ」、「Pythonのリストの長さ(要素の数)を確認する方法まとめ」、「Pythonのリストのスライスと分割方法まとめ」を読んでおくと、ここでの処理が理解しやすくなります。
len 関数で、インデックスと要素を取り出すには、次のように書きます。
'''リストを作ります。'''
list = ["zero", "one", "two"]
'''ここから for in 文です。'''
for i in range(len(list)): # インデックス番号 0 から順に要素をスライスします。
list_item = list[i] # list 関数でリストの要素の数の分ループします。
print(f"{i}: {list_item}") #これを print してループに戻ります。
for i in range(len(list)) で、リストの要素の数と同じ回数だけ for ループを繰り返すと指定しています。上記のリストの長さは、3 なので、for in range(3) と同じことになります。その部分だけ取り出して、出力したのが以下です。
'''range(len(list)) だけを見てみましょう。'''
for i in range(len(list)):
print(i)
この番号に、for ループの繰り返しごとに取り出したリストの要素を対応させています。
しかし、パッと見て、なんだか冗長なコードに見えますし、正直、理解もしづらいです。そこで、このような処理を行いたい時は、次で解説する enumerate 関数を使います。
2. enumerate 関数でインデックスと要素を取り出す
enumerate 関数を使うと、すっきりとしたコードで、指定のイテラブルのインデックスと要素を取り出すことができます。
早速見ていきましょう。
2.1. enumerate 関数とは | for in 文で使う場合の基本書式
enumerate 関数は、イテラブルに番号を加えて、戻り値を、enumerate 型のオブジェクトで返す関数です。enumerate 型のオブジェクトは、list 関数や tuple 関数で、リストやタプルに変換することができます。
少しだけ見ていきましょう。
'''リストを作ります。'''
list = ["zero", "one", "two"]
'''enumerate 関数'''
enumerate(list)
このように <enumerate at 0x1062381f8> と見慣れない戻り値を返していますが、これが enumerate 型のオブジェクトです。この型は見慣れないですし、for in 文で enumerate 関数を使う際は、詳しく理解しておく必要はさほどありません。
この関数がどう動作しているのかは、かなりの上級者向けの内容になりますし、その知識は実務上、必要になることはありません。
そこで、ここでは、まず、次のように、 for in 文と enumerate 関数を組み合わせると、イテラブルのそれぞれの要素に番号を振って、タプルとして出力することができるということを抑えておきましょう。
'''リストを作ります。'''
list = ["zero", "one", "two"]
'''enumerate 関数と for 文'''
for i in enumerate(list):
print(i)
for in 文を書く時に、変数を 2 つ指定すると、インデックス番号と要素を、別々に取り出すことができます。
'''リストを作ります。'''
list = ["zero", "one", "two"]
'''enumerate 関数と for 文'''
for i, j in enumerate(list):
print(f"{i}: {j}")
これを知っておくと、イテラブルから、インデックス番号と値を、素早く取り出すことができるようになります。
具体的な基本書式は次の通りです。
'''for in 文への enumerate 関数の書き方'''
for 変数1, 変数2 in enumerate(リスト):
print(f"{変数1} {変数2}")
最後の行の f”{}{}” という書き方ですが、これは Python 3.6 から使えるようになった非常に便利でスッキリした書き方です。これが使えるようになるまでは print( “{0}{1}”.format(変数1, 変数2)) という書き方が主流でした。
私は前者を好んで使っています。「Python の文字列変数で知っておきたい操作まとめ」で解説していますので、ぜひご覧ください。
それでは for in 文と enumerate 関数を使って、それぞれのイテラブルのインデックスと要素を取り出してみましょう。
2.2. リストやタプルのインデックス番号と要素を取り出す
まずは、リストからインデックス番号と要素を取り出してみましょう。
'''リストを作ります。'''
list = ["zero", "one", "two"]
'''リストのインデックス番号と値を取り出します。'''
for index, value in enumerate(list):
print(f"{index}: {value}")
これは for index, value in enumerate(list) で、変数 index にインデックス番号を、変数 value にリストの要素を代入して、print で 1 つずつ出力しています。
タプルの場合も同じです。
'''タプルを作ります。'''
tuple = ["zero", "one", "two"]
'''タプルのインデックス番号と値を取り出します。'''
for index, value in enumerate(tuple):
print(f"{index}: {value}")
2.3. 文字列のインデックス番号と要素を取り出す
for in 文は対象がイテラブルであれば、何でも可能ですので、文字列に対しても同様に処理することができます。
'''文字列など他のイテラブルでも可能です。'''
str = "million reasons"
for index, value in enumerate(str):
print("{0}: {1}".format(index, value))
このように、それぞれの文字と、それぞれに割り振られているインデックス番号を取り出すことがあできます。
余談ですが、ここでは f プリフィクス ではなく format メソッドを使って print してみました。
2.4. 辞書のインデックス番号と要素を取り出す
辞書は、上の 3 つのイテラブルと違い、要素は、キーと値の 2 つに別れています。そして値は、インデックス番号ではなく、キーによって管理されています(詳しくは「初心者のための Pythonの辞書の基本と作成方法まとめ」をご覧ください)。
そのため、
- インデックス番号とキーを取り出す。
- インデックス番号と値を取り出す。
- インデックス番号と要素(キーと値)を取り出す。
という 3 つの方法があります。
それぞれ見ていきましょう。
インデックス番号とキーを取り出す
通常の書き方をすると、キーにインデックス番号をつけて取り出します。
'''辞書を作ります。'''
dict = {"fruit1":"orange", "fruit2":"apple", "fruit3":"peach"}
'''インデックス番号と辞書のキーを取り出します。'''
for index, value in enumerate(dict):
print(f"{index}: {value}")
インデックス番号と値を取り出す
enumerate 関数の引数を入力する辞書に values メソッドを組み合わせると、インデックス番号と値を取り出します。values メソッドは「Pythonの辞書(dict)のキーの存在を調べたり取り出したりする方法」で解説しています。
'''辞書を作ります。'''
dict = {"fruit1":"orange", "fruit2":"apple", "fruit3":"peach"}
'''インデックス番号と辞書の値を取り出します。'''
for index, value in enumerate(dict.values()):
print(f"{index}: {value}")
インデックス番号と要素を取り出す
enumerate 関数の引数を入力する辞書に items メソッドを組み合わせると、インデックス番号と値を取り出します。items メソッドも「Pythonの辞書(dict)のキーの存在を調べたり取り出したりする方法」で解説しています。
'''辞書を作ります。'''
dict = {"fruit1":"orange", "fruit2":"apple", "fruit3":"peach"}
'''インデックス番号と辞書の要素を取り出します。'''
for index, value in enumerate(dict.items()):
print(f"{index}: {value}")
3. 複数のイテラブルから同時にインデックスと要素を取り出す
2 つ以上のイテラブルから、同時にインデックスと要素を取り出したい場合は、enumerate 関数と zip 関数を組み合わせて使います。
3.1. zip 関数とは
zip 関数は、複数のリストやタプルなどのイテラブルの要素を合成して、タプル型で返す関数です。以下をご覧ください。
"""リストとタプルを作ります。"""
list = ["zero", "one", "two"]
tuple = ["零", "一", "二"]
'''2 つのリストを zip 関数でまとめます。'''
zipped_lists = zip(list, tuple)
'''zip 関数はオブジェクトを zip 型 で返します。'''
print(zipped_lists)
'''これを list 関数でリスト化すると 2 つのリストの要素が合成されます。'''
print(list(zipped_lists))
'''tuple 関数でタプル化することもできます。'''
print(tuple(zipped_lists))
'''set 関数で set 化(集合化)することもできます。'''
print(set(zipped_lists))
※注: 実際は、zip 型オブジェクトは、一度、list 関数などでリスト化するとなくなってしまうので、同じ zip 型オブジェクトを使いたい場合は、新規で再度 zip 関数で作成する必要があります。
このように、同じインデックス番号を持つ要素を合成して、タプル型で返します。
zip 関数自体の戻り値は、 enumerate 関数と同じように、<zip object at 0x106490fc8> という見慣れない型で返されます。これも、for in 文で使う際は、詳しく理解しておく必要はさほどありません。zip 関数の仕組みの知識は、かなりの上級者向けの内容になりますし、実務上、必要になることは、ほとんどありません。
ここでは、zip 関数を使うと、複数のイテラブルのインデックス番号と要素を同時に取り出せるということが分かれば十分です。具体的には、次のように書きます。
''' for in 文への enumerate 関数と zip 関数の書き方'''
for 変数1, (変数2, 変数3) in enumerate(zip(イテラブル1, イテラブル2)):
print(f"{変数1}{変数2}{変数3}")
これが基本書式です。注意点ですが、変数2と変数3は括弧 () で括ります。そうすることで、これらは、zip(イテラブル1, イテラブル2)と、それぞれ対応することを Python が理解できるようになります。これを忘れるとエラーになりますので、覚えておきましょう。
それでは、zip 関数を使って、 2 つのイテラブルから同時にインデックス番号と要素を取り出していきましょう。
3.2. リストとタプルからインデックス番号と要素を取り出す
次の例では、2 つのリストから同時に、インデックス番号と要素を取り出しています。
"""2 つのリストを作ります。"""
list1 = ["zero", "one", "two"]
list2 = ["零", "一", "二"]
'''zip 関数と enumerate 関数を組み合わせます。'''
for index, (value1, value2) in enumerate(zip(list1, list2)):
print(f"{index}: {value1} - {value2}")
タプルの場合も同じです。
"""2 つのタプルを作ります。"""
tuple1 = ["zero", "one", "two"]
tuple2 = ["零", "一", "二"]
'''zip 関数と enumerate 関数を組み合わせます。'''
for index, (value1, value2) in enumerate(zip(tuple1, tuple2)):
print(f"{index}: {value1} - {value2}")
一方はリスト、他方はタプルの場合でも同じように可能です。
3.3. 文字列からインデックス番号と要素を取り出す
続いて文字列の場合も見てみましょう。
"""2 つの文字列を作ります。"""
str1 = "this is a string"
str2 = "これは文字列です。"
'''zip 関数と enumerate 関数を組み合わせます。'''
for index, (value1, value2) in enumerate(zip(str1, str2)):
print(f"{index}: {value1} - {value2}")
基本はリストやタプルの場合と全く同じですね。
ここで一つご注目頂きたいのが、取り出される要素の数です。文字列に限らず zip 関数が取り出す要素の数は、それが少ない方に合わされます。そのため、zip 関数を使う前に、対象となるイテラブルの要素の数を調べるようにすると良いでしょう。
3.4. 複数の辞書からインデックス番号と要素を取り出す
続いて、辞書の場合を見てみましょう。
インデックス番号とキーを取り出す
通常、enumerate 関数に辞書を入れると、キーが取り出されます。それは zip 関数と組み合わせた場合でも同じです。
"""2 つの辞書を作ります。"""
dict1 = {0:"zero", 1:"one", 2:"two"}
dict2 = {0:"零", 1:"一", 2:"二"}
'''zip 関数と enumerate 関数を組み合わせます。'''
for index, (value1, value2) in enumerate(zip(dict1, dict2)):
print(f"{index}: {value1} - {value2}")
キー、値、両方を指定して取り出す
取り出す要素を、指定したい場合は、以下のメソッドを使います。
- values メソッド:値を取り出したい時に使う。
- items メソッド:キーと値の両方を取り出したい時に使う。
次の例で確認しておきましょう。
"""キーと値、または両方のどれを取り出すかはメソッドで調整します。"""
dict1 = {0:"zero", 1:"one", 2:"two"}
dict2 = {0:"零", 1:"一", 2:"二"}
dict3 = {0:"α", 1:"γ", 2:"θ"}
'''ここからが for 文です。'''
for index, (value1, value2, value3) in enumerate(zip(dict1, dict2.values(), dict3.items())):
print(f"{index}: {value1} - {value2} - {value3}")
dict1 からはキーが、dict2からは値が、dict3からは両方が取り出されていますね。混乱してしまいそうな方は、上述の「2.4. 辞書のインデックス番号と要素を取り出す」をもう一度読み返してみてください。
4. まとめ
Python の for 文でインデックスを調べるには、以上のように、enumerate 関数を使います。さらに、enumerate 関数と zip 関数を組み合わせると、複数のイテラブルから同時にインデックスと要素を取り出すことができます。
最初にお見せした list 関数を使う方法は、見た目にも分かりにくいですし、処理効率も良くありません。
なお、辞書の要素を取り出す場合は、デフォルトでは、キーが取り出されます。値を取り出したい時は values メソッド、キーと値の両方を取り出したい時は、items メソッドを使います。
様々な関数やメソッドが出てきましたが、しっかりと整理して、1 つずつ使いこなせるように意識しましょう。
コメント