Вопрос-Ответ

How to remove list elements in a for loop in Python? [duplicate]

Как удалить элементы списка в цикле for в Python?

У меня есть список

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

Я хочу удалить элементы из этого списка в цикле for, как показано ниже:

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

Но это не работает. Что я могу сделать?

Переведено автоматически
Ответ 1

Вам не разрешается удалять элементы из списка во время итерации по нему с помощью for цикла.

Лучший способ переписать код зависит от того, что именно вы пытаетесь сделать.

Например, ваш код эквивалентен:

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

В качестве альтернативы вы могли бы использовать while цикл:

while a:
print(a.pop())

Я пытаюсь удалить элементы, если они соответствуют условию. Затем я перехожу к следующему элементу.


Вы могли бы скопировать каждый элемент, который не соответствует условию, во второй список:

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 ...]

где ... обозначает условие, которое вам нужно проверить.

Ответ 2

Выполнить итерацию по копии списка:

>>> 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']
Ответ 3

As other answers have said, the best way to do this involves making a new list - either iterate over a copy, or construct a list with only the elements you want and assign it back to the same variable. The difference between these depends on your use case, since they affect other variables for the original list differently (or, rather, the first affects them, the second doesn't).

If a copy isn't an option for some reason, you do have one other option that relies on an understanding of why modifying a list you're iterating breaks. List iteration works by keeping track of an index, incrementing it each time around the loop until it falls off the end of the list. So, if you remove at (or before) the current index, everything from that point until the end shifts one spot to the left. But the iterator doesn't know about this, and effectively skips the next element since it is now at the current index rather than the next one. However, removing things that are after the current index doesn't affect things.

This implies that if you iterate the list back to front, if you remove an item at the current index, everything to it's right shifts left - but that doesn't matter, since you've already dealt with all the elements to the right of the current position, and you're moving left - the next element to the left is unaffected by the change, and so the iterator gives you the element you expect.

TL;DR:

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

However, making a copy is usually better in terms of making your code easy to read. I only mention this possibility for sake of completeness.

Ответ 4
import copy

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

b = copy.copy(a)

for item in a:
print(item)
b.remove(item)
a = copy.copy(b)

Works: to avoid changing the list you are iterating on, you make a copy of a, iterate over it and remove the items from b. Then you copy b (the altered copy) back to a.

python list