2010-05-08 2 views
585
a=[1,2,3,4] 
b=a.index(6) 
del a[b] 
print a 

выше показывает следующее сообщение об ошибке:Есть ли простой способ удалить элемент списка по значению?

Traceback (most recent call last): 
    File "D:\zjm_code\a.py", line 6, in <module> 
    b=a.index(6) 
ValueError: list.index(x): x not in list 

Так что я должен сделать это:

a=[1,2,3,4] 
try: 
    b=a.index(6) 
    del a[b] 
except: 
    pass 
print a 

Но не более простой способ сделать это?

+12

Вы вычислим индекс 6 в списке. Но 6 нет в вашем списке ... так что должно случиться? :) –

+4

это не имеет ничего общего с удалением значения в списке, так как ваш код не достигает инструкции del. Может быть, вы должны отменить его «как получить индекс значения, которого нет в списке. Очевидный ответ - вы не можете. –

+39

@Dave Ну, на самом деле, он не хочет удалять элемент из списка, независимо от того, – ibz

ответ

980

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

>>> a = ['a', 'b', 'c', 'd'] 
>>> a.remove('b') 
>>> print a 
['a', 'c', 'd'] 

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

>>> a = [10, 20, 30, 40, 20, 30, 40, 20, 70, 20] 
>>> a = [x for x in a if x != 20] 
>>> print a 
[10, 30, 40, 30, 40, 70] 
+103

Сбой, если элемент отсутствует в списке. :) – ibz

+14

Понимание списка @ibz не сработает, даже если элемент не находится в списке. список, не так ли? – IsaacS

+53

Чтобы прояснить для кого-либо, что «сбой» в том смысле, что он вызывает исключение ValueError. –

59

Вы можете сделать

a=[1,2,3,4] 
if 6 in a: 
    a.remove(6) 

но выше необходимости поиска 6 Сдать в 2 раза, так что попробуйте, за исключением будет быстрее

try: 
    a.remove(6) 
except: 
    pass 
+12

Отлично. Вы объяснили, почему второй вариант является лучшим. Спасибо. –

7

Поиск значения в списке, а затем удаление этого индекса (если оно существует) проще сделать, просто используя метод удаления списка:

>>> a = [1, 2, 3, 4] 
>>> try: 
... a.remove(6) 
... except ValueError: 
... pass 
... 
>>> print a 
[1, 2, 3, 4] 
>>> try: 
... a.remove(3) 
... except ValueError: 
... pass 
... 
>>> print a 
[1, 2, 4] 

Если вы делаете это часто, вы можете обернуть его в функции:

def remove_if_exists(L, value): 
    try: 
    L.remove(value) 
    except ValueError: 
    pass 
126

Обычно Python будет сгенерировано исключение, если вы скажете ей сделать что-то он не может, так что вы должны будете сделать что-либо:

if c in a: 
    a.remove(c) 

или:

try: 
    a.remove(c) 
except ValueError: 
    pass 

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

+8

Профилактика лучше, чем лечение. Если сначала вы можете проверить исключительные условия (пример a), вам следует. – Gusdor

+62

Хотя это верно на других языках, в Python «легче просить прощения, чем разрешения». http://docs.python.org/2/glossary.html#term-eafp –

+4

@Gusdor: если список разделяется между потоками, тогда 'a.remove (c)' может выйти из строя в любом случае, несмотря на 'if c in a' check ('a' может быть изменен в другом потоке после проверки' c in a', но перед вызовом 'a.remove (c)'. 'try/except' или блокировки могут использоваться для предотвращения состояния гонки. – jfs

11

Вот как сделать это InPlace (без списка понимания):

def remove_all(seq, value): 
    pos = 0 
    for item in seq: 
     if item != value: 
      seq[pos] = item 
      pos += 1 
    del seq[pos:] 
+0

Очень умно - мне это очень нравится - к сожалению, это кажется неэффективным, как самый популярный ответ. Решение gil на самом деле намного быстрее для гигантских списков с небольшим количеством значений, которые вы хотите удалить. – Larold

+0

@Larold Самый быстрый способ - это отдельный вопрос. В общем случае мои деньги хранятся в списках. Это решение должно работать очень хорошо, если значение часто встречается во входном списке, и понимание списка не используется. Попробуйте Pypy, numpy данные в Cython. [@ Ответ Гилла - «O (n * n)» без необходимости (сравните 1e6 и 1e12 - вы не хотите рисковать последним). 'while 1: L.remove (value)', а return на 'ValueError' может хорошо работать с несколькими' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'или '' '' '' '' '' в CPython. – jfs

10

Если вы знаете, какое значение для удаления, вот простой способ (так просто, как я могу думать, так или иначе):

a = [0, 1, 1, 0, 1, 2, 1, 3, 1, 4] 
while a.count(1) > 0: 
    a.remove(1) 

Вы получите [0, 0, 2, 3, 4]

+4

Почему бы не использовать 'while 1 in a:' как структуру цикла? – TerminalDilettante

+9

Это 'O (n^2)', где понимание будет «O (n)». –

+1

Конечно, @MadPhysicist прав, а версия TerminalDilettante намного более питонична, даже если мы не заботимся о производительности. В 2013 году я только начал изучать Python, и в настоящее время я часто стыжусь того, что я написал тогда. – gil

36

Рассмотрим:

a = [1,2,2,3,4,5] 

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

a = list(filter(lambda x: x!= 2, a)) 

Таким образом, он будет держать все элементы = 2!.

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

a.remove(2) 
+0

Почему вы завершаете ['filter()'] (https://docs.python.org/2/library/functions.html#filter) в другом 'list()'?Согласно руководству, он уже возвращает список. –

+3

@OlafDietsche В Python 3.x он возвращает объект фильтра (в 2.x, он возвращает список), поэтому мне нужно указать «a» в список, чтобы он имел любую функциональность. – mathwizurd

+0

Спасибо за это объяснение. Я не смотрел на Python 3. –

0

Да. Это то, что я нашел, чтобы быть наиболее полезным:

import sys 

a = [1, 2, 3, 4] 

y = 0 

if y < 1: 
     a.remove(1) 
     print len(a) 
else: 
    sys.exit() 

Теперь .remove() принимает только один аргумент, так что вы можете удалить только одно целое число из списка.

+0

@JohnColeman Я просто заявляю о решении, о котором спрашивает вопрос. Я нашел это «самым полезным» для себя, у вас есть право не согласиться. – ozy

+3

Принятый ответ от много лет назад уже упомянул 'remove', поэтому вы ничего нового не добавляете, только новая вещь заключается в том, что без видимой причины вы ввели' sys.exit() '. Кроме того, ваш метод выходит из строя, если целевой элемент отсутствует в списке, и вся точка вопроса OP заключается в том, как удалить элементы без сбоев, когда метод был применен к элементу, не входящему в список. –

5

Этот пример очень быстро и удалит все экземпляры значения из списка:

a = [1,2,3,1,2,3,4] 
while True: 
    try: 
     a.remove(3) 
    except: 
     break 
print a 
>>> [1, 2, 1, 2, 4] 
7

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

IE, если данные не заказывали, и не имеет дубликатов, то

my_set=set([3,4,2]) 
my_set.discard(1) 

безошибочность.

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

my_set.add(3) 

не изменяет my_set сверху.

4

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

c = [1,2,3,4,'x',8,6,7,'x',9,'x'] 
z = list(set(c) - set(['x'])) 
print z 
[1, 2, 3, 4, 6, 7, 8, 9] 
2

Мы можем также использовать .pop:

>>> lst = [23,34,54,45] 
>>> remove_element = 23 
>>> if remove_element in lst: 
...  lst.pop(lst.index(remove_element)) 
... 
23 
>>> lst 
[34, 54, 45] 
>>> 
1

Переписать список путем индексации все, за исключением элементов, которые вы хотите удалить

>>> s = [5,4,3,2,1] 
>>> s[0:2] + s[3:] 
[5, 4, 2, 1] 
2

С для петли и условия:

def cleaner(seq, value):  
    temp = []      
    for number in seq: 
     if number != value: 
      temp.append(number) 
    return temp 

И если вы хотите удалить некоторые, но не все:

def cleaner(seq, value, occ): 
    temp = [] 
    for number in seq: 
     if number == value and occ: 
      occ -= 1 
      continue 
     else: 
      temp.append(number) 
    return temp 
1
list1=[1,2,3,3,4,5,6,1,3,4,5] 
n=int(input('enter number')) 
while n in list1: 
    list1.remove(n) 
print(list1) 
+0

Он не использует функцию фильтра –

1

Скажем, например, мы хотим, чтобы удалить все 1 из х. Это, как я бы об этом:

x = [1, 2, 3, 1, 2, 3] 

Теперь это практическое использование моего метода:

def Function(List, Unwanted): 
    [List.remove(Unwanted) for Item in range(List.count(Unwanted))] 
    return List 
x = Function(x, 1) 
print(x) 

И это мой метод в одной строке:

[x.remove(1) for Item in range(x.count(1))] 
print(x) 

Оба дают это как выход:

[2, 3, 2, 3, 2, 3] 

Надеюсь, это поможет. PS, пожалуйста, обратите внимание, что это было написано в версии 3.6.2, поэтому вам может потребоваться настроить его для более старых версий.

3

Как указано многочисленными другими ответами, list.remove() будет работать, но сбросьте ValueError, если этого элемента нет в списке. С питоном 3.4+, есть интересный подход к решению этого, используя в suppress contextmanager:

from contextlib import suppress 
with suppress(ValueError): 
    a.remove('b') 
0

Я считаю, что это самый быстрый способ когда-либо

a = [10,20,30,20,10,50,60,40,80,50,40] 

dup_items = set() 
uniq_items = [] 
    for x in a: 
    if x not in dup_items: 
     uniq_items.append(x) 
     dup_items.add(x) 

print(dup_items) 
+0

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

Смежные вопросы