Pythonは非常に高度なプログラミング言語であり、内部データ構造に似たものから遠ざかる傾向があります。
このため、通常はリストの要素にアクセスするためにインデックスを必要としませんが、時にはどうしてもインデックスが必要な場合があります。
この記事では、Pythonのforループでインデックスにアクセスする方法について、さまざまなアプローチで説明します。
Pythonのfor LoopでIndexにアクセスするには?
for ループで要素のインデックスにアクセスする最も簡単で人気のある方法は、リストの長さを調べて index
を増加させることです。
インデックスを増やすごとに、そのインデックスにあるリストにアクセスします。
my_list = [3, 5, 4, 2, 2, 5, 5]
print("Indices and values in my_list:")
for index in range(len(my_list)):
print(index, my_list[index], end = "
")
ここでは、通常行うようなリスト内の繰り返し処理は行いません。
0..len(my_list)から
indexを使って繰り返し処理を行います。
そして、このindex変数を使用して、リストの要素を
0..n(ここで
n` はリストの最後) の順番でアクセスします。
このコードでは、次のような出力が得られます。
Indices and values in my_list:
0 3
1 5
2 4
3 2
4 2
5 5
6 5
enumerate()を使用する
enumerate()` は Python の組み込み関数で、リストの値とインデックスの両方にアクセスしたいときに非常に便利です。
これは、forループでインデックスを取得するための最も速く、最も効率的な方法であることは注目に値します。
このメソッドは、反復処理可能なオブジェクトにカウンタを追加し、それらをまとめて列挙オブジェクトとして返します。
この列挙型オブジェクトは、コンストラクタ list()
を用いて簡単にリストに変換することができます。
これは、要素とそのインデックスの両方に同時にアクセスするための最も一般的な方法です。
では、このメソッドがどのように使われるかを示すコードを見てみましょう。
my_list = [3, 5, 4, 2, 2, 5, 5]
print("Indices and values in my_list:")
for index, value in enumerate(my_list):
print(list((index, value)))
このコードは次のような出力を生成します。
Indices and values in my_list:
[0, 3]
[1, 5]
[2, 4]
[3, 2]
[4, 2]
[5, 5]
[6, 5]
この例では、リスト内のすべての値とそのインデックスを列挙して、enumerateオブジェクトを作成しています。
そして、その列挙オブジェクトを list()
コンストラクタを使ってリストに変換し、各リストを標準出力に出力しました。
さらに、 start
引数を設定することで、インデックスの付け方を変更することができます。
現在は0ベースです。
代わりに 1
から始まるように変更してみましょう。
my_list = [3, 5, 4, 2, 2, 5, 5]
print("Indices and values in my_list:")
for index, value in enumerate(my_list, start=1):
print(list((index, value)))
これで、次のように出力されます。
Indices and values in my_list:
[1, 3]
[2, 5]
[3, 4]
[4, 2]
[5, 2]
[6, 5]
[7, 5]
リスト内包の利用
リスト内包は、既存のリストを元にリストを定義したり作成したりする方法です。
通常、関数や for
ループに比べてより速く、よりエレガントで、よりコンパクトなリスト操作の方法です。
Pythonのすべてのリスト内包は以下の3つの要素を含んでいます。
iterable – 一度に1つの要素を検査することができるコレクション。
member – リスト内の値またはオブジェクト(イテレート可能)。
式 – 値を返す有効な式(メンバー、反復可能、関数呼び出しなど)。
次の例を見てみよう。
my_list = [1, 2, 3, 4, 5]
my_list_squared = [m*m for m in my_list]
print(my_list_squared)
このコードは、次のような出力を生成する。
[1, 4, 9, 16, 25]
このリスト内包では、 my_list
がイテラブル、 m
がメンバー、 m*m
が式を表しています。
リスト内包が何であるかを理解したところで、リスト内包を使ってリストを反復処理し、そのインデックスと対応する値にアクセスできるようになりました。
では、この例を見てみましょう。
my_list = [3, 5, 4, 2, 2, 5, 5]
print("Indices and values in my_list:")
print([list((i, my_list[i])) for i in range(len(my_list))])
このコードは次のような出力を生成します。
Indices and values in my_list:
[[0, 3], [1, 5], [2, 4], [3, 2], [4, 2], [5, 5], [6, 5]]
この例でやったことは、list()
コンストラクタを使うことです。
このコンストラクタは引数を取らないか、あるいは単一の引数であるイテラブルを取ります。
これには、シーケンス(文字列、タプル)やコレクション(セット、ディクショナリ)である可能性のあるあらゆるオブジェクトが含まれます。
引数が渡されない場合は空のリストを返し、引数としてイテラブルが渡された場合は、その項目からなるリストを作成します。
ここでは,[elementIndex, elementValue]
という形式の2つの要素からなるリストを作成しました.これらの2要素リストは、コンストラクタ list()
にペアを渡すことで作成され、コンストラクタは同等のリストを生成します。
これは、 my_list
のインデックスとそれに対応する値を含む7つの個別のリストを作成し、それを表示するものです。
zip()の使用
関数 zip()
は 2 つ以上のパラメータを受け付けますが、これらはすべてイテレート可能でなければなりません。
これは zip オブジェクトを返します。
つまり、渡された各イテレータの最初の項目がペアとなり、渡された各イテレータの 2 番目の項目がペアとなり、残りの項目も同様にペアとなる、タプルのイテレータを指します。
list_a = [1, 2, 3]
list_b = ['A', 'B', 'C']
# Zip will make touples from elements with the same
# index (position in the list). Meaning that 1 from the
# first list will be paired with 'A', 2 will be paired
# with 'B' and so on...
for elem1,elem2 in zip(list_a,list_b):
print((elem1,elem2))
上のコードを実行すると、次のようになります。
(1, 'A')
(2, 'B')
(3, 'C')
この関数が返すイテレータの長さは、パラメータのうち最も小さいものの長さと等しくなります。
さて、この関数がどのように動作するかを説明したところで、この関数を使って課題を解決してみましょう。
my_list = [3, 5, 4, 2, 2, 5, 5]
print ("Indices and values in my_list:")
for index, value in zip(range(len(my_list)), my_list):
print((index, value))
このコードは、次のような出力を生成する。
Indices and values in my_list:
(0, 3)
(1, 5)
(2, 4)
(3, 2)
(4, 2)
(5, 5)
(6, 5)
この例では、zip()
関数の最初のパラメータとして 0
から len(my_list)
までの範囲の数列を渡し、その 2 番目のパラメータとして my_list
を渡しています。
この関数では、各インデックスとそれに対応する値をペアにして、 for
ループを使用してタプルとして出力しました。
もし、これらのタプルをリストに変換したければ、 list()
コンストラクタを使用し、 print
関数はこのようになります。
print(list((index, value)))
結論
この記事では、Pythonのリスト内のインデックスとそれに対応する値にアクセスするための4つの異なるメソッドについて説明しました。
最も基本的なメソッドに加えて、リスト内包の基礎と、それらがこのタスクを解決するためにどのように使用できるかを見てきました。
一般的なforループに比べて高速な方法であっても、リスト内包自体があまりにも複雑になる場合は、一般的にそれを使用することは避けるべきです。
複雑なリスト内包は、多くの面倒なコードにつながる可能性があります。
注意すべきは、すべてのリスト内包がforループに書き換えられるとしても、すべてのforループがリスト内包に書き換えられるとは限らないということです。
もう1つの方法は、Pythonの組み込み関数に依存する方法です。
enumerate()とzip()
は、インデックスとそれに対応する値をまとめてタプルにするPythonの組み込み関数です。
そして、これらのタプルをリストに変換し、標準出力に表示しました。