Я ищу способ удалить все значения из списка из другого списка.
Что-то вроде этого:
a = range(1,10)
a.remove([2,3,7])
print a
a = [1,4,5,6,8,9]
Я ищу способ удалить все значения из списка из другого списка.
Что-то вроде этого:
a = range(1,10)
a.remove([2,3,7])
print a
a = [1,4,5,6,8,9]
>>> a = range(1, 10)
>>> [x for x in a if x not in [2, 3, 7]]
[1, 4, 5, 6, 8, 9]
Если у вас нет повторяющихся значений, вы можете использовать разницу в настройках.
x = set(range(10))
y = x - set([2, 3, 7])
# y = set([0, 1, 4, 5, 6, 8, 9])
а затем при необходимости преобразуется обратно в список.
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
или внутри понимания. Если вы это сделаете, он будет воссоздан на каждой итерации, полностью разбив точку использования набора.
Я искал быстрый способ сделать этот вопрос, поэтому я сделал несколько экспериментов с предложенными способами. И я был удивлен результатами, поэтому хочу поделиться им с вами.
Эксперименты проводились с использованием инструмента 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 раз быстрее, чем понимание списка!
Другие предложили способы создания нового списка после фильтрации, например.
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
, это проще.
Самый простой способ -
>>> 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]
>>> 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]
Чтобы удалить список из списка, вы можете обратиться к индексу подписок, который хотите удалить, например:
a = [[1,2],[3,4],[5,6]]
a.remove(a[1]) # removes the second sublist