106

私はリストを持っています

a = ["a", "b", "c", "d", "e"]

以下のようなforループでこのリストの要素を削除したい:

for item in a:
    print(item)
    a.remove(item)

しかし、うまくいきません。私に何ができる?

4

6 に答える 6

151

forループを使用してリストを反復処理しているときに、リストから要素を削除することは許可されていません。

コードを書き直す最善の方法は、何をしようとしているのかによって異なります。

たとえば、コードは次と同等です。

for item in a:
    print(item)
a[:] = []

whileまたは、ループを使用できます。

while a:
    print(a.pop(0))

条件に一致するアイテムを削除しようとしています。それから次の項目に行きます。

条件に一致しないすべての要素を 2 番目のリストにコピーできます。

result = []
for item in a:
    if condition is False:
        result.append(item)
a = result

filterまたは、リスト内包表記を使用して、結果を に代入することもできますa

a = filter(lambda item:... , a)

また

a = [item for item in a if ...]

where...は、確認する必要がある条件を表します。

于 2012-05-19T13:32:42.277 に答える
86

リストのコピーを反復処理します。

>>> a = ["a", "b", "c", "d", "e"]
>>> for item in a[:]:
    print(item)
    if item == "b":
        a.remove(item)

a
b
c
d
e
>>> print(a)
['a', 'c', 'd', 'e']
于 2012-05-19T13:37:06.020 に答える
25

他の回答が言っているように、これを行う最善の方法は、新しいリストを作成することです.コピーを繰り返すか、必要な要素だけでリストを作成して同じ変数に割り当てます. これらの違いは、元のリストの他の変数に異なる影響を与えるため、ユース ケースによって異なります (または、最初の変数はそれらに影響し、2 番目の変数は影響しません)。

何らかの理由でコピーができない場合は、反復しているリストを変更すると壊れる理由を理解する必要がある別のオプションがあります。リストの反復は、インデックスを追跡し、リストの最後から外れるまでループのたびにインクリメントすることで機能します。したがって、現在のインデックス (またはその前) で削除すると、その時点から最後までのすべてが 1 スポット左にシフトします。しかし、反復子はこれを認識せず、次の要素ではなく現在のインデックスにあるため、次の要素を効果的にスキップします。ただし、現在のインデックスより後のものを削除しても影響はありません。

これは、リストを後ろから前に繰り返す場合、現在のインデックスの項目を削除すると、その右側のすべてが左にシフトすることを意味しますが、それは問題ではありません。現在の位置であり、左に移動しています。左の次の要素は変更の影響を受けないため、反復子は期待する要素を提供します。

TL;DR:

>>> a = list(range(5))
>>> for b in reversed(a):
    if b == 3:
        a.remove(b)
>>> a
[0, 1, 2, 4]

ただし、通常、コードを読みやすくするという点では、コピーを作成する方が適切です。完全を期すために、この可能性についてのみ言及します。

于 2012-05-19T13:59:07.443 に答える
4

新しいリストを作成し、その新しいリストに必要な要素を追加するのはどうですか。リストを繰り返し処理している間は要素を削除できません

于 2012-05-19T13:33:47.300 に答える
2

おそらくこれに答えるには少し遅れますが、このスレッドを見つけたばかりで、以前に独自のコードを作成していました...

    list = [1,2,3,4,5]
    deleteList = []
    processNo = 0
    for item in list:
        if condition:
            print(item)
            deleteList.insert(0, processNo)
        processNo += 1

    if len(deleteList) > 0:
        for item in deleteList:
            del list[item]

それは長い道のりかもしれませんが、うまく機能しているようです。削除するリスト項目に関連する番号のみを保持する 2 つ目のリストを作成します。「挿入」はリスト項目番号を位置 0 に挿入し、残りをプッシュするので、項目を削除するときに、リストは最大番号から最小番号に戻って削除されるため、リストは順番に維持されます。

于 2015-03-28T05:39:56.910 に答える