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

944
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)

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

zjm1126
источник
14
Вы рассчитываете индекс 6 в вашем списке. Но 6 не в вашем списке ... так что должно произойти? :)
Йоханнес Чарра
5
это не имеет ничего общего с удалением значения в списке, поскольку ваш код не достигает оператора del. Может быть, вам следует переформулировать это «как мне получить индекс значения, которого нет в списке. Очевидный ответ - вы не можете».
Дейв Кирби,
57
@ Дэйв Ну, не совсем. Он хочет удалить элемент из списка независимо от того, существует он или нет, чтобы не получить индекс для несуществующего элемента. Вопрос хорошо задан.
IBZ
Кроме того, голый except- плохая практика . Используйте except Exceptionкак минимум.
wjandrea

Ответы:

1568

Чтобы удалить первое вхождение элемента в списке, просто используйте 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]
Йоханнес Чарра
источник
144
Сбой, если элемента нет в списке. :)
IBZ
21
Понимание списка @ibz не перестает работать, даже если элемент отсутствует в списке, не так ли?
Исаак
76
Чтобы прояснить для любого скимминга, он «терпит неудачу» в том смысле, что вызывает исключение ValueError.
Кейси Фальк
10
Понимание списка изменяет ссылку на список, поэтому, если где-то есть копия ссылки, удаление не последует.
Себастьян
В чем сложность removeO (n)?
Расми Ранджан Наяк
184

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

if c in a:
    a.remove(c)

или:

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

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

Дэйв Уэбб
источник
9
Профилактика лучше лечения. Если вы можете сначала проверить наличие исключительных условий (пример а), вам следует.
Гусдор
82
Хотя это верно и для других языков, в Python «проще просить прощения, чем разрешения». docs.python.org/2/glossary.html#term-eafp
Дейв Уэбб
6
@Gusdor: если список распределяется между потоками, то в a.remove(c)любом случае может произойти сбой, несмотря на if c in aпроверку ( aможет быть изменен в другом потоке после c in aпроверки, но перед a.remove(c)вызовом). try/exceptили замки могут быть использованы, чтобы избежать состояния гонки.
Jfs
7
@JFSebastian, если список разделен между потоками, и вы не применяете критические разделы, тогда у вас большие проблемы.
Гусдор
4
@Gusdor, идиома Pythonique - пытаться без проверки и поймать исключение, если оно произойдет. Это более эффективно (только один поиск вместо двух), хотя и немного уродливее
Джит
80

Ты можешь сделать

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

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

try:
    a.remove(6)
except:
    pass
ВЫ
источник
55

Рассматривать:

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

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

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

Таким образом, он сохранит все элементы a != 2.

Чтобы вынуть один из предметов, используйте

a.remove(2)
mathwizurd
источник
Почему вы завернули filter()в другое list()? Согласно инструкции, он уже возвращает список.
Олаф Дитче
8
@OlafDietsche В Python 3.x он возвращает объект фильтра (в 2.x он возвращает список), поэтому я должен привести «a» к списку, чтобы он имел какую-либо функциональность.
mathwizurd
17

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

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]
JFS
источник
Очень умно - мне это очень нравится - к сожалению, оно кажется таким же неэффективным, как и самый популярный ответ. Решение gil на самом деле намного быстрее для гигантских списков с несколькими случаями значения, которое вы хотите удалить.
Larold
1
@Larold Самый быстрый способ - это отдельный вопрос. Мои деньги находятся в списке понимания в общем случае. Это решение должно работать очень хорошо, если значение часто встречается в списке ввода, а понимание списка не используется. Попробуйте Pypy, NumPy данные в Cython. [@ Gill ответ O(n*n)излишне (сравните 1e6 и 1e12 - вы не хотите рисковать последним). while 1: L.remove(value)и return on ValueErrorможет хорошо работать с несколькими values или небольшими списками в CPython.
Jfs
13

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

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
12
Это O(n^2)где понимание будет O(n).
Безумный физик
1
Конечно, @MadPhysicist прав, а версия TerminalDilettante гораздо более питонна, даже если нам не важна производительность. В 2013 году я только начал изучать Python, и в настоящее время мне довольно часто стыдно за то, что я написал тогда.
Гил
11

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

То есть если ваши данные не упорядочены и не имеют дубликатов, то

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

без ошибок.

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

my_set.add(3)

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

GreenAsJade
источник
10

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

from contextlib import suppress
with suppress(ValueError):
    a.remove('b')
Фельк
источник
8

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

>>> 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

источник
8

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

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]
Чейз Адамс
источник
2
если вы делаете это, вы должны только breakна except ValueError.
Энтон
8

В одну строку:

a.remove('b') if 'b' in a else None

иногда это полезно.

Еще проще:

if 'b' in a: a.remove('b')
Андрей Суглобов
источник
7

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

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]
Pagol
источник
2
Если ваши элементы различны, и вы не заботитесь о порядке .
Том Зыч
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]
>>> 
SuperNova
источник
2

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

>>> s = [5,4,3,2,1]
>>> s[0:2] + s[3:]
[5, 4, 2, 1]
килоджоулей
источник
2

С циклом for и условием:

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
user7970984
источник
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)
Равикиран Д
источник
Это без использования функции фильтра
Ravikiran D
1

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

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, поэтому вам может потребоваться настроить его для более старых версий.

Кронус Мелавея
источник
1

Может быть, ваши решения работают с целочисленными, но у меня не работает со словарями.

С одной стороны, удаление () не работает для меня. Но, возможно, это работает с основными типами. Я предполагаю, что приведенный ниже код также является способом удаления элементов из списка объектов.

С другой стороны, «del» тоже не работает должным образом. В моем случае, используя python 3.6: когда я пытаюсь удалить элемент из списка с помощью команды «for» с помощью команды «del», python изменяет индекс в процессе, и bucle останавливается раньше времени. Это работает, только если Вы удаляете элемент за элементом в обратном порядке. Таким образом, вы не изменяете индекс массива ожидающих элементов, когда проходите его

Затем я использовал:

c = len(list)-1
for element in (reversed(list)):
    if condition(element):
        del list[c]
    c -= 1
print(list)

где 'list' похож на [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Также Вы можете сделать больше pythonic используя перечисление:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)
Дэвид Мартинес
источник
0
arr = [1, 1, 3, 4, 5, 2, 4, 3]

# to remove first occurence of that element, suppose 3 in this example
arr.remove(3)

# to remove all occurences of that element, again suppose 3
# use something called list comprehension
new_arr = [element for element in arr if element!=3]

# if you want to delete a position use "pop" function, suppose 
# position 4 
# the pop function also returns a value
removed_element = arr.pop(4)

# u can also use "del" to delete a position
del arr[4]
Бриеш Кушваха
источник
0

Это удаляет все экземпляры "-v"из массива sys.argvи не выдает жалоб, если экземпляры не были найдены:

while "-v" in sys.argv:
    sys.argv.remove('-v')

Вы можете увидеть код в действии, в файле с именем speechToText.py:

$ python speechToText.py -v
['speechToText.py']

$ python speechToText.py -x
['speechToText.py', '-x']

$ python speechToText.py -v -v
['speechToText.py']

$ python speechToText.py -v -v -x
['speechToText.py', '-x']
Майк Слинн
источник
-1

это мой ответ, просто используйте время и для

def remove_all(data, value):
    i = j = 0
    while j < len(data):
        if data[j] == value:
            j += 1
            continue
        data[i] = data[j]
        i += 1
        j += 1
    for x in range(j - i):
        data.pop()
guoxy2016
источник