Python: リストをループで処理する

リストをループで処理する

 

課題

リストをループで処理する際に、ループに使用しているリストの要素を削除すると、削除した要素の次の要素がスキップされる。

 

例えば、以下を実行すると、

# リストの要素を表示
list1 = [6, 1, 8, 0, 3]
print("リストの要素を表示")
for item in list1:
print(item)

 

以下のようになる。これは想定通り。

 

・実行結果

リストの要素を表示
6
1
8
0
3

 

しかし、以下を実行すると、

# リストの要素を削除すると、次の要素が飛ばされる
print("リストの要素を表示: 途中で要素を削除すると、その次の要素が表示されない。(この例だと 8 が処理されない)")
list1 = [6, 1, 8, 0, 3]
for item in list1:
print(item)
if item == 1:
list1.remove(item)
print("リストの全要素を表示: 想定通り 1 は削除された")
print(list1)

 

 

・実行結果

リストの要素を表示: 途中で要素を削除すると、その次の要素が表示されない。(この例だと 8 が処理されない)
6
1
0
3
リストの全要素を表示: 想定通り 1 は削除された
[6, 8, 0, 3]

 

想定とは異なり、上記のように削除した "1" の次の "8" がループに含まれないため、完全な処理ができない。

 

 

ちなみに、以下を実行しても、全ての要素を削除することはできない。remove() すると、次の要素がループに含まれないためである。

# リストの要素を全削除するつもりでやってみてもうまくいかない
print("リストの要素を表示: リストの要素を全削除したいと思ってもスキップされるのでうまくいかない")
list1 = [6, 1, 8, 0, 3]
for item in list1:
print(item)
list1.remove(item)
print("削除は 1つ飛ばしで行われる。従って、1 0 が残ってしまう")
print(list1)

 

・実行結果

リストの要素を表示: リストの要素を全削除したいと思ってもスキップされるのでうまくいかない
6
8
3
削除は 1つ飛ばしで行われる。従って、1 と 0 が残ってしまう
[1, 0]

 

 

対応案

ループ用と処理用の 2つのリストを用意し、処理用ループで要素の削除をすることで、リストの全要素が処理対象となるようにする。以下の例では、list1 がループ用で list2 が処理用である。

# 対応案1: ループ用とは別にリストを用意し、数値の処理はそのリストで行う
import copy

# 配列初期化
list1 = [6, 1, 8, 0, 3]

# list のコピーには、copy.copy を使う。普通に代入すると、同一のリストを参照してしまう。
list2 = copy.copy(list1)

print("ループを list1 で行い、数値の処理は list2 で行う")
for item in list1:
print(item)
if item == 1:
# print("数値処理は list2 で行う")
list2.remove(item)

print("リスト1 の全要素を表示", end="")
print(list1)

print("リスト2 の全要素を表示", end="")
print(list2)

 

 

・実行結果

ループを list1 で行い、数値の処理は list2 で行う
6
1
8
0
3
リスト1 の全要素を表示[6, 1, 8, 0, 3]
リスト2 の全要素を表示[6, 8, 0, 3]