Чи є простий спосіб видалити елемент списку за значенням?


942
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
@Dave Ну, не дуже. Він хоче видалити елемент зі списку незалежно від того, існує він чи ні, не отримувати індекс для неіснуючого елемента. Добре задається питання.
ibz

Крім суті, але голою exceptє погана практика . Використовуйте except Exceptionяк мінімум.
wjandrea

Відповіді:


1564

Для видалення першого елемента в списку просто використовуйте 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 не виходить з ладу, навіть якщо елемента немає у списку, чи не так?
IsaacS

76
Щоб уточнити для будь-кого, хто ским, він "провалюється" в тому сенсі, що він створює виняток ValueError.
Кейсі Фолк

10
Зрозуміння списку змінює посилання на список, тому, якщо десь є копія посилання, видалення не відбуватиметься.
Себастьян

Яка складність removeце O (n)?
Rasmi Ranjan Nayak

184

Зазвичай Python викине Виняток, якщо ви скажете йому зробити щось, чого не може, тому вам доведеться робити і таке:

if c in a:
    a.remove(c)

або:

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

Виняток - це не обов'язково погана річ, якщо ви очікуєте та належним чином поводитесь із ним.


9
Профілактика краще, ніж лікування. Якщо ви можете спочатку перевірити наявність виняткових умов (приклад a), вам слід.
Гусдор

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 полягає в тому, щоб спробувати без перевірки і зловити виняток, якщо це трапляється. Це ефективніше (лише один пошук замість двох), хоч і трохи потворніше
Jeet

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 насправді набагато швидше для гігантських списків із лише кількома явищами значення, яке ви хочете усунути.
Ларольд

1
@Larold Найшвидший спосіб був би окремим питанням. Мої гроші перебувають у розумінні списку в загальному випадку. Це рішення повинно працювати дуже добре, якщо значення часто в списку вводу та розуміння списку не використовується. Спробуйте Pypy, numpy дані в Cython. [@ Відповідь Гілла O(n*n)зайва (порівняйте 1e6 та 1e12 - ви не хочете ризикувати останнім). while 1: L.remove(value)і повернення 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, і сьогодні я досить часто соромлюсь того, що тоді писав.
gil

11

Іншою можливістю є використання набору замість списку, якщо набір застосований у вашій програмі.

IE, якщо ваші дані не упорядковані і не мають копій, значить

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
Якщо ваші елементи виразні і вам не байдуже до порядку .
Tom Zych

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

Можливо, ваші рішення працюють із ints, але це не працює для мене зі словниками.

З одного боку, видалити () не працює для мене. Але, можливо, це працює з базовими типами. Я думаю, що наведений нижче код також є способом видалення елементів зі списку об'єктів.

З іншого боку, "del" також не працював належним чином. У моєму випадку, використовуючи python 3.6: коли я намагаюся видалити елемент зі списку в команді 'for' bucle за допомогою команди 'del', python змінює індекс у процесі і bucle зупиняється передчасно. Він працює лише в тому випадку, якщо ви видаляєте елемент за елементом у зворотному порядку. Таким чином, ви не змінюєте індекс масиву відкладених елементів, коли ви проходите через нього

Потім я використав:

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

де "список" виглядає як [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Також ви можете зробити більше пітонічних, використовуючи перерахування:

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.