Remove All Occurrences of a Value from a List

Remove all occurrences of a value from a list?

Functional approach:

Python 3.x

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]

or

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]

Python 2.x

>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]

How to remove all occurrences of an element from list in Python?

There is no remove_all method or anything like that, but the best ways to accomplish this are with a list comprehension or filter.

Assuming that ls only contains other lists you can write the following to remove all occurrences of the empty list []:

List Comprehension

ls = [[1], [1, 2], [1, 2, 3], [], [2], [2, 3], [], [], [3]]
ls = [x for x in ls if x]
# now ls = [[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

Filter

ls = [[1], [1, 2], [1, 2, 3], [], [2], [2, 3], [], [], [3]]
ls = list(filter(None, ls))
# now ls = [[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

Generalizing for more than just the empty list

If you wanted to remove all occurrences of a given element elem (that is not the empty list) you can modify the above code as follows:

ls = [x for x in ls if x != elem]

##### or #####

ls = list(filter(lambda x: x != elem, ls))

Remove all occurrences of a value from a list in linear time

Normally, you would use a list comprehension, a generator expression or the filter function, but since your teacher insists on in-place processing, you can't use those. As much as I hate side-effects, here you are:

def remove_occurences(lst, val):
# using filter in Python 3 (or ifilter in Python 2) requires O(1) memory;
# it's not usually a good thing to update the object you are iterating,
# but here we can be sure, nothing will go wrong: we can never overwrite
# a value we must take before getting hold of its reference
i = -1
for i, value in enumerate(filter(lambda x: x != val, lst)):
lst[i] = value
# remove the tail
del lst[i+1:len(lst)]
return lst

Since we are dealing with imperative code, it's imperative to test it

from hypothesis import strategies as st
from hypothesis import given

@given(st.lists(elements=st.integers(0, 9), min_size=0, average_size=50, max_size=100),
st.integers(0, 9))
def test(lst, val):
assert remove_occurences(lst[:], val) == list(filter(lambda x: x != val, lst))

Calling test() will run several hundred random tests. The function has passed the tests. Now, since del on lists takes O(n) on average, we must make sure, that our tail-hack is a special case (which is most likely implementation dependent, but I guess the people behind CPython are clever enough to have optimised it long ago). Let's run some benchmarks:

In [45]: %timeit remove_occurences([1, 2, 3, 4, 5]*1, 3)
1.31 µs ± 30.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [46]: %timeit remove_occurences([1, 2, 3, 4, 5]*10, 3)
6.9 µs ± 243 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [47]: %timeit remove_occurences([1, 2, 3, 4, 5]*100, 3)
68.3 µs ± 5.82 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [48]: %timeit remove_occurences([1, 2, 3, 4, 5]*1000, 3)
733 µs ± 54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [49]: %timeit remove_occurences([1, 2, 3, 4, 5]*10000, 3)
7.07 ms ± 295 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

The growth is clearly linear. That is actually expected, considering the source (see the comment)

...
if (value == NULL) {
/* delete slice */
PyObject **garbage;
size_t cur;
Py_ssize_t i;
int res;

if (slicelength <= 0)
return 0;

if (step < 0) {
stop = start + 1;
start = stop + step*(slicelength - 1) - 1;
step = -step;
}

garbage = (PyObject**)
PyMem_MALLOC(slicelength*sizeof(PyObject*));
if (!garbage) {
PyErr_NoMemory();
return -1;
}

/* drawing pictures might help understand these for
loops. Basically, we memmove the parts of the
list that are *not* part of the slice: step-1
items for each item that is part of the slice,
and then tail end of the list that was not
covered by the slice */
...

Since we are deleting the tail, there is nothing to move, making it effectively a linear operation.

How can I remove all occurrences of one number in a list in Python

Just use list comprehension:

x = [1,1,1,2,3,3,4,5,5,5,6,7]
x = [i for i in x if i != 1]

Output:

[2, 3, 3, 4, 5, 5, 5, 6, 7]

Remove all occurrences of item(s) in list if it appears more than once

You could do:

def solution(data, n):
for x in set(data):
if data.count(x) > n:
while x in data:
data.remove(x)
return data

Some explanation:

  • set(data) makes that every value is checked only once, even if it occurs multiple times in data;
  • you should remove the continue statement, it does not do what you probably want it to do;
  • look carefully what I am doing with the if statement and the while statement;
  • in your code, the n argument was not used, I assumed that it should replace the 1 in the if-line.

Update: Here is the one line version!

solution = lambda data, n: [x for x in set(data) if data.count(x) <= n]

You can call the solution function the same as before.
If you are puzzled about this syntax, you could search 'python list comprehensions' and 'python lambda'.

How to remove all the occurrences of a certain value in a Python list?

Since you ask how to remove elements, I would re-assign the list as a slice.

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> a[:] = [item for item in a if item != 333]

This will create a new list in memory, normally thats acceptable, but if you want to avoid this without calling remove, which would check against the same items multiple times.

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> for i in range(len(a) - 1, -1, -1): # iterate over reversed indices's
>>> if a[i] == 333:
>>> del a[i]

This has the advantage that it removes the last items first (which is faster in CPython).

Note that removing items from the beginning-middle of lists in Python is not so optimal. no matter which method you use (del list[index] or list.remove), if the list is large and many items have to be removed this means Python needs to resize the list a lot, in that case I would recommend using list-comprehension to make a new list.

JavaScript remove all occurrences of a value from an array

Issue is related to the sibling 97s - 1, 32, 97, 97, 6. When you splice the first 97 in this order, the next 97 changes it's index and goes into the first one. but variable i is tracking after that item.

When you remove an item, decrease the index via --i.

Also you can do it via filter function. This will create a new array and you just need to return it. Here I have created and object with input array and a function which filters the input and returns the current object. This will let you to cascade the functions which I think is beautiful from the code style and can help you in something.

const obj = {   input: [3, 97, 32, 6, 97, 2, 9,32, 1, 32, 97, 97, 6, -1, 5],   removeItem(item) {      this.input = this.input.filter(i => i !== item);      return this;   }}
const output = obj.removeItem(97) .removeItem(32) .removeItem(6); console.log(output.input);

How to remove all occurrences?

Consider querying,

?- remove(x, [x,a,b,c,x,d], R).

The problem with code 2 is that at some point, after extracting all the elements in the 2nd list, it becomes empty. At this point, upon recursion, the only possible choice is the first clause because the 2nd and 3rd clause requires that the list to have a head, which it doesn't because its empty.

Thus, it tries to perform unification with the first. Now, the first 2 predicates are fine, but the last one is problematic.

Namely, it tries to unify [] = [d, c, b, a | _free_ ]. Which is not possible because [] is not a 'free variable'

My terminologies might be wrong however... but I believe the essence is there.



Related Topics



Leave a reply



Submit