Как удалить элементы из списка во время итерации? - PullRequest
853 голосов
/ 30 июля 2009

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

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

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

Ответы [ 26 ]

1 голос
/ 16 марта 2018

Остальные ответы верны: обычно плохая идея удалять из списка, который вы повторяете. Обратная итерация позволяет избежать ловушек, но гораздо сложнее следовать коду, который делает это, поэтому обычно вам лучше использовать понимание списка или filter.

Однако существует один случай, когда безопасно удалить элементы из последовательности, которую вы повторяете: если вы удаляете только один элемент во время итерации. Это может быть обеспечено с помощью return или break. Например:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

Это часто легче понять, чем понимание списка, когда вы выполняете некоторые операции с побочными эффектами для первого элемента в списке, который удовлетворяет некоторому условию, а затем сразу удаляете этот элемент из списка.

0 голосов
/ 29 мая 2019

опровергнуть список чисел, и вы хотите удалить все нет, которые делятся на 3,

list_number =[i for i in range(100)]

с использованием list comprehension, это создаст новый список и создаст новое пространство памяти

new_list =[i for i in list_number if i%3!=0]

с использованием функции lambda filter, это создаст результирующий новый список и будет занимать пространство памяти

new_list = list(filter(lambda x:x%3!=0, list_number))

без использования места в памяти для нового списка и изменения существующего списка

for index, value in enumerate(list_number):
    if list_number[index]%3==0:
        list_number.remove(value)
0 голосов
/ 16 апреля 2019

Если вы будете использовать новый список позже, вы можете просто установить элемент на None, а затем оценить его в последующем цикле, как это

for i in li:
    i = None

for elem in li:
    if elem is None:
        continue

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

0 голосов
/ 21 сентября 2018

В некоторых ситуациях, когда вы делаете больше, чем просто фильтруете список по одному элементу за раз, вы хотите, чтобы ваша итерация менялась во время итерации.

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

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p
0 голосов
/ 23 августа 2018

Для всего, что может быть действительно большим, я использую следующее.

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

Это должно быть значительно быстрее, чем все остальное.

0 голосов
/ 01 июля 2017

Сразу же вы хотите создать копию списка, чтобы иметь ее в качестве справочной, когда вы выполняете итерации и удаляете кортежи в этом списке, которые соответствуют определенным критериям.

Тогда это зависит от того, какой тип списка вы хотите выводить, будь то список удаленных кортежей или список не удаленных кортежей.

Как указал Дэвид, я рекомендую использовать списки, чтобы сохранить элементы, которые вы не хотите удалять.

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