Удалите несколько элементов из списка Python всего за одно утверждение

В python я знаю, как удалить элементы из списка.

item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)

Этот выше код удаляет значения 5 и "item" из item_list. Но когда есть много вещей для удаления, я должен написать много строк

item_list.remove("something_to_remove")

Если я знаю индекс того, что я удаляю, я использую:

del item_list[x]

где x - индекс элемента, который я хочу удалить.

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

Но что, если я не знаю индексов элементов, которые хочу удалить?

Я пробовал item_list.remove('item', 'foo'), но получил ошибку, говоря, что remove принимает только один аргумент.

Есть ли способ удалить несколько элементов из списка в одном выражении?

P.S. Я использовал del и remove. Может ли кто-то объяснить разницу между этими двумя, или они одинаковы?

Спасибо

Ответы

Ответ 1

В Python создание нового объекта часто лучше, чем изменение существующего:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

Что эквивалентно:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
    if e not in ('item', 5):
        new_list.append(e)
item_list = new_list

В случае большого списка отфильтрованных значений (здесь ('item', 5) - это небольшой набор элементов), использование set может привести к повышению производительности, поскольку операция in находится в O (1)

item_list = [e for e in item_list if e not in {'item', 5}]

Обратите внимание, что, как объяснено в комментариях и предложено здесь, следующее может сэкономить еще больше времени, избегая установки, которая будет построена в каждом цикле

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

A bloom filter также является хорошим решением, если память не дешевая.

Ответ 2

item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove=['item', 5, 'foo']

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

final_list=[3.14, True]

Одиночный код

final_list= list(set(item_list).difference(set(list_to_remove)))

вывод будет следующим:

final_list=[3.14, True]

Ответ 3

Но что, если я не знаю индексов элементов, которые хочу удалить?

Я не совсем понимаю, почему вам не нравится .remove, но чтобы получить первый индекс, соответствующий значению, используйте .index(значение):

ind=item_list.index('item')

затем .pop, чтобы удалить соответствующее значение:

item_list.pop(ind)

.index(значение) получает первое вхождение значения, а .remove(значение) удаляет первое вхождение значения

Ответ 4

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


def removed(val, list_, only_duplicates=False, inplace=False):
    """By default 'removes' given values from list_ and returns
    a new list. Optionally only removes duplicates or modifies
    given list in place.

    Remove all duplicates by passing whole list to val.

    Examples:
    \>>>li1 = [1, 2, 3, 4, 4, 5, 5]
    \>>>removed(4, li1)
       [1, 2, 3, 5, 5]
    \>>>removed((4,5), li1)
       [1, 2, 3]
    \>>>removed((4,5), li1, only_duplicates=True)
       [1, 2, 3, 4, 5]

    # remove all duplicates:
    \>>>removed(li1, li1, only_duplicates=True)
      [1, 2, 3, 4, 5]

    # inplace:
    \>>>removed((4,5), li1, only_duplicates=True, inplace=True)
    \>>>li1
        [1, 2, 3, 4, 5]

    \>>>li2 =['abc', 'def', 'def', 'ghi', 'ghi']
    \>>>removed(('def', 'ghi'), li2, only_duplicates=True, inplace=True)
    \>>>li2
        ['abc', 'def', 'ghi']
    """
    if not hasattr(val, '__iter__') or isinstance(val, str):
        val = [val]
    if only_duplicates:
        _list = []
        [_list.append(i) for i in list_ if i not in _list or i not in val]
    else:
        _list = [i for i in list_ if i not in val]

    if inplace:
        list_[:] = _list
    else:
        return _list

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

li1 = [1, 2, 3, 4, 4, 5, 5]
li2 = li1
# then rebind li1 to the new list without the value 4
li1 = removed(4, li1)
# you end up with two separate lists where li2 is still pointing to the 
# original
li2
# [1, 2, 3, 4, 4, 5, 5]
li1
# [1, 2, 3, 5, 5]

Это может быть или не быть поведением, которое вы хотите.