classification
Title: list.Count() isn't working as expected for the series of same numbers in a list
Type: behavior Stage: resolved
Components: Versions: Python 3.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: cmaliwal, remi.lapeyre, steven.daprano
Priority: normal Keywords:

Created on 2020-05-28 16:33 by cmaliwal, last changed 2020-05-28 17:06 by steven.daprano. This issue is now closed.

Files
File name Uploaded Description Edit
test.py cmaliwal, 2020-05-28 16:33 Sample code
Messages (5)
msg370239 - (view) Author: chirag maliwal (cmaliwal) Date: 2020-05-28 16:33
a = [1,1,1,1]

for i in a:
    if a.count(i) > 1:
        a.remove(i)
 
print(a)


"""
Output:
[1,1]


expected:
[1]
"""
msg370241 - (view) Author: Rémi Lapeyre (remi.lapeyre) * Date: 2020-05-28 16:39
Hi cmaliwal! You are mutating the list while iterating over it which can lead to all sorts of issues, to keep the unique elements of a list you can do 


>>> a = [1, 1, 1, 1]
>>> list(set(a))
[1]


If you think you found a bug in Python please check in the python-help mailing list or StackOverflow.
msg370245 - (view) Author: chirag maliwal (cmaliwal) Date: 2020-05-28 16:44
a = [0, 1, 2, 3, 4, 1, 2, 3, 5]

for i in a:
    if a.count(i) > 1:
        a.remove(i)

print(a)

"""
Output

[0, 4, 1, 2, 3, 5]
"""

It's working fine for the above code.
Yes I can use set for this but I tried with count and remove.
msg370251 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-05-28 17:04
Rémi is correct, this is not a bug.

The problem isn't with list.count. If you print list.count each time through the loop, you will see that it is working perfectly. 

The problem is that you are modifying the list as you are iterating over it. That means that you skip every second item. It isn't easy to see when all the items are the same, but we can alternate int and float values (which are equal) to see how every second value is skipped.


py> a = [1, 1.0, 1, 1.0, 1, 1.0, 1, 1.0]
py> for i in a:
...     print(a, i, a.count(i))
...     if a.count(i) > 1:
...             a.remove(i)
...
[1, 1.0, 1, 1.0, 1, 1.0, 1, 1.0] 1 8
[1.0, 1, 1.0, 1, 1.0, 1, 1.0] 1 7
[1, 1.0, 1, 1.0, 1, 1.0] 1 6
[1.0, 1, 1.0, 1, 1.0] 1 5
py> a
[1, 1.0, 1, 1.0]


Notice that every one of the float 1.0 values gets skipped. That's because when you resize the list as you walk over it, the value which *would have been* the next value gets pushed back into the current position, and then you advance to the next position, and skip it.

So there's no bug in list.count, it is working perfectly each time. There's no bug in iteration either, it is walking the list correctly too. But there is a bug in your code: you are shrinking the list while walking over it, so on each step, you delete one item from the from and step forward, so you skip items.

The lesson here is not to delete items from a list while you are iterating over it.

Technically, it's okay to delete items so long as they are *ahead* of the current item, but not if they are *behind* it. But it is easiest to just use the rule, never delete items while iterating over the same list.

If you must delete items from a list, iterate over a copy.
msg370252 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-05-28 17:06
Typo:

"on each step, you delete one item from the from and step forward"

Should be, you delete one item from the FRONT and step forward.
History
Date User Action Args
2020-05-28 17:06:35steven.dapranosetmessages: + msg370252
2020-05-28 17:04:50steven.dapranosetstatus: open -> closed

nosy: + steven.daprano
messages: + msg370251

resolution: not a bug
stage: resolved
2020-05-28 16:44:29cmaliwalsetmessages: + msg370245
2020-05-28 16:39:12remi.lapeyresetnosy: + remi.lapeyre

messages: + msg370241
title: list.count() isn't working as expected for the series of same numbers in a list -> list.Count() isn't working as expected for the series of same numbers in a list
2020-05-28 16:37:19cmaliwalsettitle: list.Count() isn't working as expected for the series of same numbers in a list -> list.count() isn't working as expected for the series of same numbers in a list
2020-05-28 16:33:22cmaliwalcreate