Узнайте, как удалять элементы из списка в Python, перебирая его в цикле. Есть несколько подводных камней, которых следует избегать.
Очень распространенной задачей является перебор списка и удаление некоторых элементов в зависимости от условия. В этой статье показаны различные способы , как это сделать, а также показаны некоторые распространенные ловушки, которых следует избегать .
Допустим, нам нужно изменить список a
и удалить все нечетные элементы. У нас есть эта маленькая вспомогательная функция, чтобы определить, является ли число четным или нет.
a = [1, 2, 2, 3, 4] def even(x): return x % 2 == 0
Вариант 1. Создайте новый список, содержащий только те элементы, которые вы не хотите удалять
1a) Нормальное понимание списка
Используйте генератор списков, чтобы создать новый список, содержащий только те элементы, которые вы не хотите удалять, и верните его в a.
a = [x for x in a if not even(x)] # --> a = [1, 3]
1b) Понимание списка путем назначения срезаa[:]
Приведенный выше код создал новую переменную a
. Мы также можем изменить существующий список на месте, назначив фрагменту a[:]
. Этот подход более эффективен и может быть полезен, если есть другие ссылки на a
то, что необходимо отразить изменения.
a[:] = [x for x in a if not even(x)] # --> a = [1, 3]
1с) Использованиеitertools.filterfalse()
Модуль itertools предоставляет различные функции для очень эффективного цикла, а также предлагает метод фильтрации элементов:
from itertools import filterfalse a[:] = filterfalse(even, a) # --> a = [1, 3]
Вариант 2. Перебрать копию
Если вы действительно хотите сохранить синтаксис цикла for , вам нужно перебрать копию списка (копия просто создается с помощью a[:]
). Теперь вы можете удалять элементы из исходного списка, если условие истинно.
for item in a[:]: if even(item): a.remove(item) # --> a = [1, 3]
Чего не делать
Не перебирайте один и тот же список и не изменяйте его во время итерации!
Это тот же код, что и выше, за исключением того, что здесь мы не повторяем копию. Удаление элемента сдвинет все последующие элементы на одно место влево, поэтому в следующей итерации один элемент будет пропущен. Это может привести к неверным результатам.
for item in a: if even(item): a.remove(item) # --> a = [1, 2, 3] !!!
Кроме того, никогда не изменяйте индекс во время цикла по списку!
Это неверно, потому что изменение i внутри цикла НЕ повлияет на значение i в следующей итерации . Этот пример также производит нежелательные эффекты и даже приводит к ошибкам IndexError, как здесь.
for i in range(len(a)): if even(a[i]): del a[i] i -= 1 # --> IndexError: list index out of range