0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Listから複数要素を削除する際に注意する点

Posted at

何が起きた

リスト内に削除する要素が複数あり、何も考えずにループしながら削除して行ったら条件に一致するのに削除されない要素が見つかった。

原因

至ってシンプルで、リストの先頭から走査して削除したため、インデックスと要素の組み合わせがおかしくなり、本来削除される要素が残ってしまった。

対処方法

リストを逆順から走査するよう変更

対処前

lst = [1, 2, 3]
for i in lst:
    if i in (1, 2):
        lst.remove(i)
print(lst)
# 実行結果
[2, 3]

対処後

lst = [1, 2, 3]
for I in reversed(lst):
    if i in (1, 2):
        lst.remove(i)
print(lst)
# 実行結果
[3]

解説

リストの頭から削除すると要素が詰められるがインデックスはそのまま。
このため削除された次の要素が詰められてしまい処理されない。
リストを後ろから削除することで次に判定される要素が詰められることを防ぐ。

検証

対応前

>>> lst = [1, 2, 3]
>>> for i, l in enumerate(lst):
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...     if l in (1, 2):
...             lst.remove(l)
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...
index:0, value:1, list:[1, 2, 3]
index:0, value:1, list:[2, 3]
index:1, value:3, list:[2, 3]
index:1, value:3, list:[2, 3]

indexが1の時点でvalueが3になっているため、本来であれば判定で除去されなければならない2が処理されていない。(元のリスト通りならindexが1の時、valueは2)
これを逆順で行う。

対応後

>>> lst = [1, 2, 3]
>>> for i, l in enumerate(reversed(lst)):
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...     if l in (1, 2):
...             lst.remove(l)
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...
index:0, value:3, list:[1, 2, 3]
index:0, value:3, list:[1, 2, 3]
index:1, value:2, list:[1, 2, 3]
index:1, value:2, list:[1, 3]
index:2, value:1, list:[1, 3]
index:2, value:1, list:[3]

気をつけるべき事柄

ここまでは要素で削除を行った場合。
気をつけなければならないのは、インデックスで削除を行う場合。
インデックスで削除する場合、この書き方ではエラーになってしまう。

>>> lst = [1, 2, 3]
>>> for i, l in enumerate(reversed(lst)):
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...     if l in (1, 2):
...             del lst[i]
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...
index:0, value:3, list:[1, 2, 3]
index:0, value:3, list:[1, 2, 3]
index:1, value:2, list:[1, 2, 3]
index:1, value:2, list:[1, 3]
index:2, value:1, list:[1, 3]
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
IndexError: list assignment index out of range

この場合は以下の以下のようにすれば対応できる。

>>> lst = [1, 2, 3]
>>> for i, l in reversed(list(enumerate(lst))):
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...     if l in (1, 2):
...             del lst[i]
...     print("index:%s, value:%s, list:%s" % (i, l, lst))
...
index:2, value:3, list:[1, 2, 3]
index:2, value:3, list:[1, 2, 3]
index:1, value:2, list:[1, 2, 3]
index:1, value:2, list:[1, 3]
index:0, value:1, list:[1, 3]
index:0, value:1, list:[3]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?