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


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.