'Remove multiple items from a Python list in just one statement
In python, I know how to remove items from a list:
item_list = ['item', 5, 'foo', 3.14, True]
item_list.remove('item')
item_list.remove(5)
The above code removes the values 5 and 'item' from item_list.
But when there is a lot of stuff to remove, I have to write many lines of:
item_list.remove("something_to_remove")
If I know the index of what I am removing, I use:
del item_list[x]
where x is the index of the item I want to remove.
If I know the index of all of the numbers that I want to remove, I'll use some sort of loop to del the items at the indices.
But what if I don't know the indices of the items I want to remove?
I tried item_list.remove('item', 'foo'), but I got an error saying that remove only takes one argument.
Is there a way to remove multiple items from a list in a single statement?
P.S. I've used del and remove. Can someone explain the difference between these two, or are they the same?
Solution 1:[1]
You can do it in one line by converting your lists to sets and using set.difference:
item_list = ['item', 5, 'foo', 3.14, True]
list_to_remove = ['item', 5, 'foo']
final_list = list(set(item_list) - set(list_to_remove))
Would give you the following output:
final_list = [3.14, True]
Note: this will remove duplicates in your input list and the elements in the output can be in any order (because sets don't preserve order). It also requires all elements in both of your lists to be hashable.
Solution 2:[2]
You can use filterfalse function from itertools module
Example
import random
from itertools import filterfalse
random.seed(42)
data = [random.randrange(5) for _ in range(10)]
clean = [*filterfalse(lambda i: i == 0, data)]
print(f"Remove 0s\n{data=}\n{clean=}\n")
clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1s\n{data=}\n{clean=}")
Output:
Remove 0s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 1, 1, 1, 4, 4]
Remove 0s and 1s
data=[0, 0, 2, 1, 1, 1, 0, 4, 0, 4]
clean=[2, 4, 4]
Solution 3:[3]
I'm reposting my answer from here because I saw it also fits in here. It allows removing multiple values or removing only duplicates of these values and returns either a new list or modifies the given list in place.
def removed(items, original_list, only_duplicates=False, inplace=False):
"""By default removes given items from original_list and returns
a new list. Optionally only removes duplicates of `items` or modifies
given list in place.
"""
if not hasattr(items, '__iter__') or isinstance(items, str):
items = [items]
if only_duplicates:
result = []
for item in original_list:
if item not in items or item not in result:
result.append(item)
else:
result = [item for item in original_list if item not in items]
if inplace:
original_list[:] = result
else:
return result
Docstring extension:
"""
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 by passing original_list also to `items`.:
>>>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']
"""
You should be clear about what you really want to do, modify an existing list, or make a new list with the specific items missing. It's important to make that distinction in case you have a second reference pointing to the existing list. If you have, for example...
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]
This may or may not be the behaviour you want.
Solution 4:[4]
I don't know why everyone forgot to mention the amazing capability of sets in python. You can simply cast your list into a set and then remove whatever you want to remove in a simple expression like so:
>>> item_list = ['item', 5, 'foo', 3.14, True]
>>> item_list = set(item_list) - {'item', 5}
>>> item_list
{True, 3.14, 'foo'}
>>> # you can cast it again in a list-from like so
>>> item_list = list(item_list)
>>> item_list
[True, 3.14, 'foo']
Solution 5:[5]
You Can use this -
Suppose we have a list, l = [1,2,3,4,5]
We want to delete last two items in a single statement
del l[3:]
We have output:
l = [1,2,3]
Keep it Simple
Solution 6:[6]
But what if I don't know the indices of the items I want to remove?
I do not exactly understand why you do not like .remove but to get the first index corresponding to a value use .index(value):
ind=item_list.index('item')
then remove the corresponding value:
del item_list[ind]
.index(value) gets the first occurrence of value, and .remove(value) removes the first occurrence of value. You are welcome.
Solution 7:[7]
Suppose we have my_list as below. We would like to remove the duplicated 0's from our list. By using remove(), only one 0 can be removed, whereas the next code can remove all the duplicated 0's at once:
my_list = [1, 2, 3, 0, 0, 0, 3, 4]
list(filter(lambda a: a != 0, my_list))
output:
[1, 3, 3, 4]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Boris Verkhovskiy |
| Solution 2 | Vlad Bezden |
| Solution 3 | |
| Solution 4 | Anwarvic |
| Solution 5 | |
| Solution 6 | nocturne |
| Solution 7 | A. chahid |
