tags:

views:

1892

answers:

3

In Python remove() will remove the first occurrence of value in a list.

How to remove all occurrences of a value from a list, without sorting the list?

This is what I have in mind.

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> def remove_values_from_list(the_list, val):
        while val in the_list:
            the_list.remove(val)

>>> remove_values_from_list(x, 2)
>>> 
>>> x
[1, 3, 4, 3]
+11  A: 

You can use a list comprehension:

def remove_values_from_list(the_list, val):
   return [value for value in the_list if value != val]

x = [1, 2, 3, 4, 2, 2, 3]
x = remove_values_from_list(x, 2)
print x
# [1, 3, 4, 3]
mhawke
But, this way, it will check for each item in the list.
Selinap
How would you remove items without checking them?
Alexander Ljungberg
This doesn't modify the original list but returns a new list.
John Y
@Alexander Ljungberg: Is there a way to reduce the number of checking?
Selinap
@Selinap: No, this is optimal as it scans the list only once. In your original code both the `in` operator and `remove` method scan the entire list (up until they find a match) so you end up scanning the list multiple times that way.
John Kugelman
@Selinap: if you structure your data ahead of time in something like a binary tree you can hunt down all instances of a certain value without having to check all values in the data. What are you trying to accomplish?
Alexander Ljungberg
@John Y: "This doesn't modify the original list but returns a new list"... and then rebinds it - probably much faster than removing in place.
mhawke
@mhawke, @John Y: just use x[:] = ... instead of x = and it will be "in-place" rather than just rebinding the name 'x' (speed is essentially the same and MUCH faster than x.remove can be!!!).
Alex Martelli
Removing in-place can be very fast if you don't care about the order: move the last item over the one you're deleting, then when you're done scanning, truncate the items off the end. If you're not removing many elements, this may be faster in a lower level language--it moves less memory around. I suspect it's a wash in Python.
Glenn Maynard
Doing x[:] = y is probably going to make a second memory copy of the list, though, which will be slower (not by much, at least for typical small lists).
Glenn Maynard
+5  A: 

Functional approach:

>>> x = [1,2,3,2,2,2,3,4]
>>> filter (lambda a: a != 2, x)
[1, 3, 3, 4]
Mark Rushakoff
Yes, I like this too
mhawke
Use the list comprehension over the filter+lambda; the former is more readable in addition to generally more efficient.
Aaron Gallagher
s/generally/generally being/
Aaron Gallagher
+6  A: 

You can use slice assignment if the original list must be modified, while still using an efficient list comprehension (or generator expression).

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]
Coady
This is what filter do right.
Selinap
@Selinap: filter does not modify the list, it returns a new list.
Whisty
filter and list comprehensions don't modify a list. slice assignment does. and the original example does.
Coady