Удалите несколько элементов из списка 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]
Это может быть или не быть поведением, которое вы хотите.