Удалить все значения в одном списке из другого списка?

Я ищу способ удалить все значения из списка из другого списка.

Что-то вроде этого:

a = range(1,10)  
a.remove([2,3,7])  
print a  
a = [1,4,5,6,8,9]  

Ответ 1

>>> a = range(1, 10)
>>> [x for x in a if x not in [2, 3, 7]]
[1, 4, 5, 6, 8, 9]

Ответ 2

Если у вас нет повторяющихся значений, вы можете использовать разницу в настройках.

x = set(range(10))
y = x - set([2, 3, 7])
# y = set([0, 1, 4, 5, 6, 8, 9])

а затем при необходимости преобразуется обратно в список.

Ответ 3

a = range(1,10)
itemsToRemove = set([2, 3, 7])
b = filter(lambda x: x not in itemsToRemove, a)

или

b = [x for x in a if x not in itemsToRemove]

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

Ответ 4

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

Эксперименты проводились с использованием инструмента pythonbenchmark и с

a = range(1,50000) # Source list
b = range(1,15000) # Items to remove

Результаты:

 def comprehension(a, b):
     return [x for x in a if x not in b]

5 попыток, среднее время 12,8 с

def filter_function(a, b):
    return filter(lambda x: x not in b, a)

5 попыток, среднее время 12,6 секунд

def modification(a,b):
    for x in b:
        try:
            a.remove(x)
        except ValueError:
            pass
    return a

5 попыток, среднее время 0,27 с

def set_approach(a,b):
    return list(set(a)-set(b))

5 попыток, среднее время 0.0057 сек

Также я сделал еще одно измерение с большим размером входов для двух последних функций

a = range(1,500000)
b = range(1,100000)

И результаты:

Для модификации (метод удаления) - среднее время составляет 252 секунды Для заданного подхода - среднее время 0,75 секунд

Итак, вы можете видеть, что подход с наборами значительно быстрее, чем другие. Да, он не хранит похожие предметы, но если вам это не нужно - это для вас. И нет никакой разницы между пониманием списка и использованием функции фильтра. Использование 'remove' в ~ 50 раз быстрее, но оно изменяет список источников. И лучший выбор - использование наборов - это более чем в 1000 раз быстрее, чем понимание списка!

Ответ 5

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

newl = [x for x in l if x not in [2,3,7]]

или

newl = filter(lambda x: x not in [2,3,7], l) 

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

l = range(1,10)
for o in set([2,3,7,11]):
    try:
        l.remove(o)
    except ValueError:
        pass

print l

Выход:   [1, 4, 5, 6, 8, 9]

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

Также, если вам не требуется исправление на месте с помощью S.Mark, это проще.

Ответ 6

Самый простой способ -

>>> a = range(1, 10)
>>> for x in [2, 3, 7]:
...  a.remove(x)
... 
>>> a
[1, 4, 5, 6, 8, 9]

Одна из возможных проблем заключается в том, что каждый раз, когда вы вызываете remove(), все элементы перетасовываются по списку, чтобы заполнить отверстие. Поэтому, если a растет очень сильно, это будет довольно медленным.

Таким образом создается новый список. Преимущество состоит в том, что мы избегаем всех перетасовки первого подхода

>>> removeset = set([2, 3, 7])
>>> a = [x for x in a if x not in removeset]

Если вы хотите изменить a на месте, требуется только одно небольшое изменение

>>> removeset = set([2, 3, 7])
>>> a[:] = [x for x in a if x not in removeset]

Ответ 7

>>> a=range(1,10)
>>> for i in [2,3,7]: a.remove(i)
...
>>> a
[1, 4, 5, 6, 8, 9]

>>> a=range(1,10)
>>> b=map(a.remove,[2,3,7])
>>> a
[1, 4, 5, 6, 8, 9]

Ответ 8

Чтобы удалить список из списка, вы можете обратиться к индексу подписок, который хотите удалить, например:

a = [[1,2],[3,4],[5,6]]
a.remove(a[1])  # removes the second sublist