How to remove multiple items from a list in just one statement?

Question:

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?

Asked By: RandomCoder

||

Answers:

In Python, creating a new object e.g. with a list comprehension is often better than modifying an existing one:

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

… which is equivalent to:

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

In case of a big list of filtered out values (here, ('item', 5) is a small set of elements), using a set is faster as the in operation is O(1) time complexity on average. It’s also a good idea to build the iterable you’re removing first, so that you’re not creating it on every iteration of the list comprehension:

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

A bloom filter is also a good solution if memory is not cheap.

Answered By: aluriak

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.

Answered By: aless80

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.

Answered By: Aakash Goel

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.

Answered By: Darkonaut

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']
Answered By: Anwarvic

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 0sn{data=}n{clean=}n")


clean = [*filterfalse(lambda i: i in (0, 1), data)]
print(f"Remove 0s and 1sn{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]
Answered By: Vlad Bezden

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

Answered By: Krishna Singhal

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]
Answered By: A. chahid

we can remove multiple elements

list1=[1,2,3,4,5,200,30]

del list1[1:3]

print(list1)

[1,4,5,200,30]

Answered By: Rajesh Khangar

You can combine the numpy array and set function to end up with a new array that only shows the elements you want to keep.

import numpy as np
# given an array A:
A = [5,78,423,87,45,78,4]
# first convert your array to a numpy array
A_np = np.array(A)
# specify the indices you want to remove
inds_to_be_deleted = [3,5]
# find the remaining indices using set function
remaining_inds = list(set(range(len(A)))-set(inds_to_be_deleted))
# the new array will only contain the elements at the remaining indices
A_new = A_np[remaining_inds]

which gives you this output:
array([ 5, 78, 423, 45, 4])

Answered By: Ayman_Negm
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.