Python の `Foreach` ループでインデックスにアクセスする方法

Aliaksei Yursha 2022年4月14日
Python の `Foreach` ループでインデックスにアクセスする方法

多くの場合、Python でアイテムのコレクションをループするときは、各アイテムに関連付けられた序数も必要です。
このような数値は通常インデックスと呼ばれます。

foreach ループを実行しながらインデックスにアクセスする Python 的な方法は、組み込み関数 enumerate() を使用することです。

enumerate() は、反復可能なコレクションの各アイテムにインデックスを追加します。
次に、組み込み関数 list() を使用して、タプルのリストを取得できます。

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names))
[(0, 'Bob'), (1, 'Alice'), (2, 'John'), (3, 'Cindy')]

Python のインデックス作成は 0 から始まることに注意してください。

ただし、インデックス作成を 1 から開始する場合(たとえば、レポートデータを出力する場合)、追加の start 引数を enumerate に渡すことで簡単に実現できます。

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names), start=1)
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]

上記のアプローチは、異なるデータソースからデータを出力しているが、すべてのデータ要素にわたって一貫したインデックスを保持したい場合にも役立ちます。

>>> data_source1 = ['Bob', 'Alice', 'John', 'Cindy']
>>> data_source2 = ['Sarah', 'Jeff', 'Emily', 'Adam']
>>> list(enumerate(data_source1, start=1))
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]
>>> list(enumerate(data_source2, start=len(data_source1) + 1))
[(5, 'Sarah'), (6, 'Jeff'), (7, 'Emily'), (8, 'Adam')]

enumerate オブジェクトをリストに変換する必要はないことに注意してください。
反復可能なので、直接反復できます。

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> for idx, name in enumerate(names):
...   print(name)
...
Bob
Alice
John
Cindy

アイテムのコレクションを繰り返し処理しながらインデックスを取得する方法は他にもありますが、
しかし、enumerate() を使用することは標準的と見なされ、推奨されます。

別のオプションは、別のインデックス変数を使用し、それを手動で初期化し、
各反復で手動でインクリメントします。
しかし、そのようなアプローチは、車輪の再発明と見なされ、眉をひそめます。

enumerate() 関数が導入された PEP 279からの引用です。

この PEP は、新しい組み込み関数 enumerate() を導入して、よく使用されるループイディオムを簡素化します。iteritems() が辞書に与えるのと同じ利点を持つ、すべての反復可能なコレクションを提供します-コンパクトで、読みやすく、信頼できるインデックス表記法

コードで enumerate を使用することでパフォーマンスに影響があるかどうかを尋ねることができます。
すべての測定を自由に行うことができますが、enumeratefor-each ループ内の反復可能オブジェクトのインデックスにアクセスする慣用的な方法であることに留意してください。
慣用コードは Python メンテナーによって推奨されており、彼らは
効率的に実行します。

そして、あなたにとって最も興味があるのは、上記の PEP からの enumerate() 関数の可能な実装です。

def enumerate(collection):
    "Generates an indexed series:  (0,coll[0]), (1,coll[1]) ..."
    i = 0
    it = iter(collection)
    while 1:
        yield (i, it.next())
        i += 1

関連記事 - Python Loop