Is There a Simple Way to Delete a List Element by Value

Is there a simple way to delete a list element by value?

To remove the first occurrence of an element, use list.remove:

>>> xs = ['a', 'b', 'c', 'd']
>>> xs.remove('b')
>>> print(xs)
['a', 'c', 'd']

To remove all occurrences of an element, use a list comprehension:

>>> xs = ['a', 'b', 'c', 'd', 'b', 'b', 'b', 'b']
>>> xs = [x for x in xs if x != 'b']
>>> print(xs)
['a', 'c', 'd']

Best way to remove elements from a list

Use a list comprehension:

Scenario 1:

[item for item in my_list if 1 <= item <=5 ]

Scenario 2:

to_be_removed = {'a', '1', 2}
[item for item in my_list if item not in to_be_removed ]

Scenario 3:

[item for item in my_list if some_condition()]

Scenario 4(Nested list comprehension):

[[item for item in seq if some_condition] for seq in my_list]

Note that if you want to remove just one item then list.remove, list.pop and del are definitely going to be very fast, but using these methods while iterating over the the list can result in unexpected output.

Related: Loop “Forgets” to Remove Some Items

Difference between del, remove, and pop on lists

The effects of the three different methods to remove an element from a list:

remove removes the first matching value, not a specific index:

>>> a = [0, 2, 3, 2]
>>> a.remove(2)
>>> a
[0, 3, 2]

del removes the item at a specific index:

>>> a = [9, 8, 7, 6]
>>> del a[1]
>>> a
[9, 7, 6]

and pop removes the item at a specific index and returns it.

>>> a = [4, 3, 5]
>>> a.pop(1)
3
>>> a
[4, 5]

Their error modes are different too:

>>> a = [4, 5, 6]
>>> a.remove(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> del a[7]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a.pop(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop index out of range

How to remove an element from a list by index

Use del and specify the index of the element you want to delete:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Also supports slices:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

Here is the section from the tutorial.

How to delete an item in a list if it exists?

1) Almost-English style:

Test for presence using the in operator, then apply the remove method.

if thing in some_list: some_list.remove(thing)

The removemethod will remove only the first occurrence of thing, in order to remove all occurrences you can use while instead of if.

while thing in some_list: some_list.remove(thing)    
  • Simple enough, probably my choice.for small lists (can't resist one-liners)

2) Duck-typed, EAFP style:

This shoot-first-ask-questions-last attitude is common in Python. Instead of testing in advance if the object is suitable, just carry out the operation and catch relevant Exceptions:

try:
some_list.remove(thing)
except ValueError:
pass # or scream: thing not in some_list!
except AttributeError:
call_security("some_list not quacking like a list!")

Off course the second except clause in the example above is not only of questionable humor but totally unnecessary (the point was to illustrate duck-typing for people not familiar with the concept).

If you expect multiple occurrences of thing:

while True:
try:
some_list.remove(thing)
except ValueError:
break
  • a little verbose for this specific use case, but very idiomatic in Python.
  • this performs better than #1
  • PEP 463 proposed a shorter syntax for try/except simple usage that would be handy here, but it was not approved.

However, with contextlib's suppress() contextmanager (introduced in python 3.4) the above code can be simplified to this:

with suppress(ValueError, AttributeError):
some_list.remove(thing)

Again, if you expect multiple occurrences of thing:

with suppress(ValueError):
while True:
some_list.remove(thing)

3) Functional style:

Around 1993, Python got lambda, reduce(), filter() and map(), courtesy of a Lisp hacker who missed them and submitted working patches*. You can use filter to remove elements from the list:

is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)

There is a shortcut that may be useful for your case: if you want to filter out empty items (in fact items where bool(item) == False, like None, zero, empty strings or other empty collections), you can pass None as the first argument:

cleaned_list = filter(None, some_list)
  • [update]: in Python 2.x, filter(function, iterable) used to be equivalent to [item for item in iterable if function(item)] (or [item for item in iterable if item] if the first argument is None); in Python 3.x, it is now equivalent to (item for item in iterable if function(item)). The subtle difference is that filter used to return a list, now it works like a generator expression - this is OK if you are only iterating over the cleaned list and discarding it, but if you really need a list, you have to enclose the filter() call with the list() constructor.
  • *These Lispy flavored constructs are considered a little alien in Python. Around 2005, Guido was even talking about dropping filter - along with companions map and reduce (they are not gone yet but reduce was moved into the functools module, which is worth a look if you like high order functions).

4) Mathematical style:

List comprehensions became the preferred style for list manipulation in Python since introduced in version 2.0 by PEP 202. The rationale behind it is that List comprehensions provide a more concise way to create lists in situations where map() and filter() and/or nested loops would currently be used.

cleaned_list = [ x for x in some_list if x is not thing ]

Generator expressions were introduced in version 2.4 by PEP 289. A generator expression is better for situations where you don't really need (or want) to have a full list created in memory - like when you just want to iterate over the elements one at a time. If you are only iterating over the list, you can think of a generator expression as a lazy evaluated list comprehension:

for item in (x for x in some_list if x is not thing):
do_your_thing_with(item)
  • See this Python history blog post by GvR.
  • This syntax is inspired by the set-builder notation in math.
  • Python 3 has also set and dict comprehensions.

Notes

  1. you may want to use the inequality operator != instead of is not (the difference is important)
  2. for critics of methods implying a list copy: contrary to popular belief, generator expressions are not always more efficient than list comprehensions - please profile before complaining

Remove an element from a list of lists if the length is longer than a certain value

try something like

new_list=[x for x in connections if len(x)>=3]

Most efficient way to remove element of certain value everywhere from List? C#

You can just use List<T>.RemoveAll and pass your predicate - https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.removeall?view=net-6.0#System_Collections_Generic_List_1_RemoveAll_System_Predicate__0__ . This guaranteed to be linear complexity O(list.Count)

TheList.RemoveAll(x=>x==3);

Additionally, RemoveAll performs some GC-specific things internally, so I think in some cases this may provide some additional performance advantages against the simple hand-made loop implementation (but I'm unsure here).

If you want to do it all yourself, you can check out the implementation of RemoveAll here. Generally, it is just a while loop as in your question.

Additionally, as we can see from GitHub implementation (and as Jon Skeet mentioned in the comment) the remove operation causes the rest of list (all items after the first removed items) to be copied (shifted) on the free space, intorduced by deletion. So, if you have really huge list and/or want to remove something frequently, you may consider to switching to some other data structure, such as linked list.

Remove list element without mutation

I assume you mean that you want to create a new list without a given element, instead of changing the original list. One way is to use a list comprehension:

m = ['a', 'b', 'c']
n = [x for x in m if x != 'a']

n is now a copy of m, but without the 'a' element.

Another way would of course be to copy the list first

m = ['a', 'b', 'c']
n = m[:]
n.remove('a')

If removing a value by index, it is even simpler

n = m[:index] + m[index+1:]

python remove element from list without changing index of other elements

Perhaps you can get your desired effect with pandas:

>>> import pandas as pd
>>> L = ['a','a','b','b','c','c']
>>> df = pd.DataFrame(L)
>>> df
0
0 a
1 a
2 b
3 b
4 c
5 c

[6 rows x 1 columns]
>>> df = df.drop(3)
>>> df
0
0 a
1 a
2 b
4 c
5 c

[5 rows x 1 columns]
>>> df.loc[4]
0 c
Name: 4, dtype: object
>>> df.loc[5]
0 c
Name: 5, dtype: object


Related Topics



Leave a reply



Submit