今回は、pythonでのリストのループ処理について書いていこうと思います。
#通常
通常のループを実施します。
list1 = ['item1', 'item2', 'item3']
for item in list1:
print(item)
一般的なループとして、このやり方が普通ではないでしょうか?簡潔で分かりやすくベストなループだと思います。
ただ、この場合indexを取得することができません。ではその場合、どうしたらよいのでしょうか?
##indexを取得するには
###part1
まず、このようなやり方があります。しかし、いちいちindexを+1をしないといけないのがめんどくさいです。
list1 = ['item1', 'item2', 'item3']
index = 0
for item in list1:
print("インデックス:" + str(index) + ", 値:" + item)
index += 1
###part2
そこで、少しマシな方法にこのような方法もあります。
len関数でリストの長さを求めて、その長さ分ループを実施する方法です。
list1 = ['item1', 'item2', 'item3']
for index in range(len(list1)):
print("インデックス:" + str(index) + ", 値:" + list1[index])
さきほどとは異なり自身でindexをカウントアップしなくても良いし、すっきりします。ただ、リストの要素の値を取得するのが少し冗長に感じます。
###part3
そんな時にpythonには、enumerate関数が準備されています。
enumerate関数を使用するとインデックスと要素を同時に取得することができます。
list1 = ['item1', 'item2', 'item3']
for index, item in enumerate(list1):
print("インデックス:" + str(index) + ", 値:" + item)
これで無駄なくすっきりとループを書くことができました。
インデックスが必要な時は、enumerateを使用することをお勧めします。
#2つのリストを同時にループする
2つのリストを同時ループするときはどのように実施しますか?
普通ならindex付きのループを行い、そのindexでもう一方のリストの要素を取得すると思います。
list1 = ['item1-1', 'item1-2', 'item1-3']
list2 = ['item2-1', 'item2-2', 'item2-3']
for index in range(len(list1)):
print("リスト1:" + list1[index] + ", リスト2:" + list2[index])
この方法は、リストの件数が合わないときには成り立たないし、正直あまりきれいではありません。
リスト1のループの時にそのindexでほかのリストの要素を取得するなんて分かりにくいので、コメントをしっかり整備しないとあとで読むとき苦労します。
##zip
こういったときに役立つのがzip関数です。zip関数を利用するとそれぞれの要素をそれぞれの変数に格納してループをすることができます。
list1 = ['item1-1', 'item1-2', 'item1-3']
list2 = ['item2-1', 'item2-2', 'item2-3']
for item1, item2 in zip(list1, list2):
print("リスト1:" + item1 + ", リスト2:" + item2)
# ⇒ リスト1:item1-1, リスト2:item2-1
# ⇒ リスト1:item1-2, リスト2:item2-2
# ⇒ リスト1:item1-3, リスト2:item2-3
このように非常にきれいに2つのリストをループさせることができます。また、zipのメリットとして、要素数が異なるリストの場合でも同時にループすることができます。
list1 = ['item1-1', 'item1-2', 'item1-3']
list2 = ['item2-1', 'item2-2', 'item2-3', 'item2-4']
for item1, item2 in zip(list1, list2):
print("リスト1:" + item1 + ", リスト2:" + item2)
# ⇒ リスト1:item1-1, リスト2:item2-1
# ⇒ リスト1:item1-2, リスト2:item2-2
# ⇒ リスト1:item1-3, リスト2:item2-3
ただこの場合は、要素数が少ないほうに合わせてしまうので注意が必要です。上記の例では、リスト2の4つ目の要素が出力されていません。
また、zipの引数は、2個だけに限定されていません。以下のように3つのリストを指定することもできます。
list1 = ['item1-1', 'item1-2', 'item1-3']
list2 = ['item2-1', 'item2-2', 'item2-3']
list3 = ['item3-1', 'item3-2', 'item3-3']
for item1, item2, item3 in zip(list1, list2, list3):
print("リスト1:" + item1 + ", リスト2:" + item2 + ", リスト3:" + item3)
# ⇒ リスト1:item1-1, リスト2:item2-1, リスト3:item3-1
# ⇒ リスト1:item1-2, リスト2:item2-2, リスト3:item3-2
# ⇒ リスト1:item1-3, リスト2:item2-3, リスト3:item3-3
#各要素に何か処理する
##通常
リストの各要素に任意の処理をして新しいリストを作成したい時があると思います。
だいたいこんな感じに書くのではないでしょうか
#各要素に「-1」をつける
list1 = ['item1-1', 'item1-2', 'item1-3']
newList = []
for item in list1:
newList.append(item + "-1")
print(newList) # ⇒ ['item1-1-1', 'item1-2-1', 'item1-3-1']
この方法でももちろんできます。ただ、少しめんどくさいし、たった1つのことをしたいだけなのに3行も書かないといけないのがしんどいです。
##リスト内包表記
pythonにはリスト内包表記という記述方法があり、それを利用すると1行でこの処理を記述できます。
list1 = ['item1-1', 'item1-2', 'item1-3']
newList = [item + "-1" for item in list1]
print(newList) # ⇒ ['item1-1-1', 'item1-2-1', 'item1-3-1']
この方法だと何をしているか分かりやすく無駄がありません。
##リスト内包表記(if文あり)
また、リスト内包表記はif文を内部に記述してリストの中をフィルタリングできます。
例えば、1以外で終わる要素のみ対象にしたい場合は以下のようにします。
list1 = ['item1-1', 'item1-2', 'item1-3']
newList = [item + "-1" for item in list1 if not item.endswith("1")]
print(newList) # ⇒ ['item1-2-1', 'item1-3-1']
#最後に
今回はリストのループ処理に焦点を絞って紹介しました。
Javaをやっていて、めんどくさいな、分かりにくいなと思っていた処理がpythonでは簡単に記述できることを知り驚きました。
enumerate, zip, リスト内包表記、3つとも全部使いこなせるようにしたいですね。