How can I remove all the same objects from a list?

Hi everyone!
I’ve learned Python for weeks.
And this is my question.
How can I remove all the same objects from a list?
How to remove all the ‘5’?

list1=[1,2,5,4,3,5,5,6,7,8,5,5,5,9]

for i in list1:
    if i==5:
        list1.remove(5)
print(list1)

the result is :
[1, 2, 4, 3, 6, 7, 8, 5, 5, 9]
but there are still two “5”

You should ask this in #users, this category is for feedback on this site itself.

1 Like

thx for your reply :smiley:

Excuse me, I don’t know why it doesn’t work but I have the solution: you will have to use a while loop and put a condition on it:

list1=[1,2,5,4,3,5,5,6,7,8,5,5,5,9]

while list1.count(5) > 1:
list1.remove(5)

print(list1)

1 Like

Guys, please try to post formatted code.

Thanks.

1 Like

count does a lot of unnecessary work, it’s probably more clear (and certainly faster) to just check if the value of interest is in the list:

while 5 in list1:
    list1.remove(5)
2 Likes

The reason why it doesn’t work is that the for loop steps though the list, one element at a time, with the indexes 0, 1, 2, etc.

When you delete an element, the later elements shift down to fill the gap.

So, suppose you had [‘a’, ‘b’, ‘c’], for example.

You look at element 0, which is ‘a’, and decide to remove it.

You now have [‘b’, ‘c’].

You then look at the next element, element 1, which is ‘c’.

Unfortunately, you’ve just skipped over ‘b’.

The for loop didn’t notice that you’ve changed the list.

It’s generally recommended to make a new list instead:

list1 = [1, 2, 5, 4, 3, 5, 5, 6, 7, 8, 5, 5, 5, 9]
new_list = []

for i in list1:
    if i != 5:
        new_list.append(i)

list1 = new_list # Or maybe list1[ : ] = new_list
print(list1)
2 Likes

This is a common error when new to lists (and other structures). The OP
is modifying a structure (the list) while iterating through it.

Matthew’s further detail explains the effect nicely.

It is possible to mutate the list in place, but you need to take care to
have precise control over how the elements are examined.

Here’s an in-place version (untested):

 list1 = [1, 2, 5, 4, 3, 5, 5, 6, 7, 8, 5, 5, 5, 9]
 pos = 0
 while pos < len(list):
     if list[pos] == 5:
         list.remove(pos)
     else:
         pos += 1

Notice that in this version we either removes the current element,
which shuffles every thing else down one or we advance the pointer
(pos).

The OP’s original version effectively did a remove and an advance when
there was a 5.

The reason that it is generally recommended to make a new list is that
that approach is less error prone because it is harder to make that kind
of mistake by accident.

Cheers,
Cameron Simpson cs@cskk.id.au

1 Like

Another way to mutate in place is to iterate in place is to iterate backwards, so that shifting does not affect the iteration.

1 Like

Do you need to mutate in place? if not:

[i for i in original_list if i != 5]

1 Like

The simplest fix is probably to use:

for i in copy.deepcopy(list1):

Why do you need to deep-copy it? Surely a shallow copy would be sufficient.

Shallow copy is fine too in this case.

if you copy, you aren’t mutating in place :slight_smile:

And the nifty shorthand for that is [:]

for i in a_list[:]:
    ...
1 Like

A common idiom for removing duplicates from lists is to convert to set and back:

list1 = list(set(list1))

Caveats of this method:

  1. Does not preserve order of elements
  2. Only works if contents of list are hashable