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


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)

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


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)

Почему вы завернули 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:]

Очень умно - мне это очень нравится - к сожалению, оно кажется таким же неэффективным, как и самый популярный ответ. Решение 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 сверху.


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.
— Энтон


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]

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

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


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()
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.