Удалить все вхождения значения из списка? - PullRequest
305 голосов
/ 21 июля 2009

В Python remove() удалит первое вхождение значения в списке.

Как удалить все вхождения значения из списка?

Вот что я имею в виду:

>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]

Ответы [ 21 ]

417 голосов
/ 21 июля 2009

Функциональный подход:

2.x

>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]

3.x

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]

или

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]
184 голосов
/ 21 июля 2009

Вы можете использовать понимание списка:

def remove_values_from_list(the_list, val):
   return [value for value in the_list if value != val]

x = [1, 2, 3, 4, 2, 2, 3]
x = remove_values_from_list(x, 2)
print x
# [1, 3, 4, 3]
92 голосов
/ 21 июля 2009

Вы можете использовать назначение срезов, если необходимо изменить исходный список, но при этом использовать эффективное понимание списка (или выражение генератора).

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]
34 голосов
/ 17 октября 2014

Повтор решения первого поста более абстрактным способом:

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]
11 голосов
/ 23 ноября 2016

См. Простые решения

Решение 1:

>>> [i for i in x if i != 2]

Это вернет список, содержащий все элементы x без 2

Решение 2:

>>> while 2 in x : x.remove(2)
8 голосов
/ 04 июля 2014

Все ответы выше (кроме ответа Мартина Андерссона) создают новый список без нужных элементов, а не удаляют элементы из исходного списка.

>>> import random, timeit
>>> a = list(range(5)) * 1000
>>> random.shuffle(a)

>>> b = a
>>> print(b is a)
True

>>> b = [x for x in b if x != 0]
>>> print(b is a)
False
>>> b.count(0)
0
>>> a.count(0)
1000

>>> b = a
>>> b = filter(lambda a: a != 2, x)
>>> print(b is a)
False

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

Чтобы изменить список на месте, используйте метод, подобный этому

>>> def removeall_inplace(x, l):
...     for _ in xrange(l.count(x)):
...         l.remove(x)
...
>>> removeall_inplace(0, b)
>>> b is a
True
>>> a.count(0)
0

Что касается скорости, результаты на моем ноутбуке (все в списке из 5000 записей с удалением 1000 записей)

  • Понимание списка - ~ 400us
  • Фильтр - ~ 900us
  • .remove () loop - 50 мс

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

>>> def removeall_replace(x, l):
....    t = [y for y in l if y != x]
....    del l[:]
....    l.extend(t)
  • removeall_replace () - 450us
6 голосов
/ 08 июля 2016

вы можете сделать это

while 2 in x:   
    x.remove(2)
5 голосов
/ 11 июня 2012

Ценой читабельности, я думаю, что эта версия немного быстрее, поскольку она не заставляет какое-то время пересматривать список, таким образом, выполняя точно такую ​​же работу, которую удаление в любом случае должно сделать:

x = [1, 2, 3, 4, 2, 2, 3]
def remove_values_from_list(the_list, val):
    for i in range(the_list.count(val)):
        the_list.remove(val)

remove_values_from_list(x, 2)

print(x)
3 голосов
/ 02 февраля 2013

Чтобы удалить все дубликаты и оставить одно в списке:

test = [1, 1, 2, 3]

newlist = list(set(test))

print newlist

[1, 2, 3]

Вот функция, которую я использовал для Project Euler:

def removeOccurrences(e):
  return list(set(e))
2 голосов
/ 06 января 2011

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

category_ids.sort()
ones_last_index = category_ids.count('1')
del category_ids[0:ones_last_index]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...