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

How to remove items from a list while iterating?

Как удалить элементы из списка во время итерации?

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

for tup in somelist:
if determine(tup):
code_to_remove_tup

Что я должен использовать вместо code_to_remove_tup? Я не могу понять, как удалить элемент таким образом.

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

Вы можете использовать понимание списка для создания нового списка, содержащего только элементы, которые вы не хотите удалять:

somelist = [x for x in somelist if not determine(x)]

Или, присвоив фрагменту somelist[:], вы можете изменить существующий список, чтобы он содержал только нужные вам элементы:

somelist[:] = [x for x in somelist if not determine(x)]

Этот подход может быть полезен, если есть другие ссылки на somelist, которые должны отражать изменения.

Вместо понимания вы также могли бы использовать itertools. В Python 2:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

Или в Python 3:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)
Ответ 2

Ответы, предлагающие понимание списка, почти верны — за исключением того, что они создают совершенно новый список, а затем присваивают ему то же имя, что и старому списку, они не изменяют старый список на месте. Это отличается от того, что вы делали бы путем выборочного удаления, как в предложении Леннарта — это быстрее, но если доступ к вашему списку осуществляется через несколько ссылок, тот факт, что вы просто повторно устанавливаете одну из ссылок и не изменяете сам объект списка, может привести к незаметным катастрофическим ошибкам.

К счастью, добиться скорости понимания списка И требуемой семантики изменения на месте чрезвычайно просто — просто код:

somelist[:] = [tup for tup in somelist if determine(tup)]

Обратите внимание на тонкую разницу с другими ответами: этот ответ не присваивает barename . Он присваивает фрагменту списка, который просто оказывается всем списком, тем самым заменяя содержимое внутри того же объекта списка Python, а не просто перенося одну ссылку (из предыдущего объекта списка в новый объект списка), как в других ответах.

Ответ 3

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

Например (зависит от типа списка):

for tup in somelist[:]:
etc....

Пример:

>>> somelist = range(10)
>>> for x in somelist:
... somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
... somelist.remove(x)
>>> somelist
[]
Ответ 4
for i in range(len(somelist) - 1, -1, -1):
if some_condition(somelist, i):
del somelist[i]

Вам нужно вернуться назад, иначе это немного похоже на отпиливание ветки дерева, на которой вы сидите :-)

Пользователи Python 2: замените range на xrange, чтобы избежать создания жестко запрограммированного списка

python