Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use list.count(0), and how do I to discount the "False" item?

a.count(0) always returns 11, so what should I do to discount the False and return 10?

a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
like image 966
Tony Wang Avatar asked Sep 09 '16 05:09

Tony Wang


People also ask

How does list count work?

Introduction to Python List count() Count() is an in-built function in Python that returns the counts or, in many simple terms, how many times a given object occurs in the list. In other words, it returns the frequency of occurrence of that object within the list we are searching for.

How do you count zeros in a list?

Python List Count Zero / Non-Zero. To count the number of zeros in a given list, use the list. count(0) method call.

What is the purpose of count () method in python list?

The count() method returns the number of elements with the specified value.

How do you count a value in a list?

The count() is a built-in function in Python. It will return you the count of a given element in a list or a string. In the case of a list, the element to be counted needs to be given to the count() function, and it will return the count of the element. The count() method returns an integer value.


6 Answers

Python 2.x interprets False as 0 and vice versa. AFAIK even None and "" can be considered False in conditions. Redefine count as follows:

sum(1 for item in a if item == 0 and type(item) == int)

or (Thanks to Kevin, and Bakuriu for their comments):

sum(1 for item in a if item == 0 and type(item) is type(0))

or as suggested by ozgur in comments (which is not recommended and is considered wrong, see this), simply:

sum(1 for item in a if item is 0)  

it may (“is” operator behaves unexpectedly with integers) work for small primary types, but if your list contains objects, please consider what is operator does:

From the documentation for the is operator:

The operators is and is not test for object identity: x is y is true if and only if x and y are the same object.

More information about is operator: Understanding Python's "is" operator

like image 151
Ahmad Siavashi Avatar answered Oct 17 '22 11:10

Ahmad Siavashi


This can be done with sum and a generator expression that compares each element to False:

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> sum((x == 0 and x is not False) for x in a)
10

This works because bool is a subclass of int - False equals 0 and True equals 1.

like image 26
Aran-Fey Avatar answered Oct 17 '22 12:10

Aran-Fey


You need to filter out the Falses yourself.

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> len([x for x in a if x == 0 and x is not False])
10

Old answer is CPython specific and it's better to use solutions that work on all Python implementations.

Since CPython keeps a pool of small integer objects, zero included, you can filter the list with the is operator.

This of course shouldn't be used for value comparisons but in this case it works since zeros are what we want to find.

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> [x for x in a if x is 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> len(_)
10
like image 25
Sevanteri Avatar answered Oct 17 '22 10:10

Sevanteri


How about this functional style solution:

print zip(a, map(type, a)).count((0, int))
>>> 10

Timing this against some of the other answers here, this also seems to be one of the quickest:

t0 = time.time()
for i in range(100000):
    zip(a, map(type, a)).count((0, int))
print time.time() - t0
>>> 0.275855064392

t0 = time.time()
for i in range(100000):
    sum(1 for item in a if item == 0 and type(item) == int)
print time.time() - t0
>>> 0.478030204773

t0 = time.time()
for i in range(100000):
    sum(1 for item in a if item == 0 and type(item) is type(0))
print time.time() - t0
>>> 0.52236700058

t0 = time.time()
for i in range(100000):
    sum((x==0 and x is not False) for x in a)
print time.time() - t0
>>> 0.450266122818
like image 32
kezzos Avatar answered Oct 17 '22 11:10

kezzos


Solving this problem more generally, you could make your own subclass of list:

class key_equality_list(list):
    def __init__(self, key, items):
        super(key_equality_list, self).__init__(items)
        self._f = key

    def __contains__(self, x):
        return any(self._f(x) == self._f(item) for item in self)

    def count(self, x):
        return sum(self._f(x) == self._f(item) for item in self)

And then define a key function that checks types:

type_and_val = lambda x: (x, type(x))

So your usage becomes:

>>> a = ["a",0,0,"b",None,"c","d",0,1,False,0,1,0,3,[],0,1,9,0,0,{},0,0,9]
>>> a = key_equality_list(type_and_val, a)
>>> a.count(0)
10
>>> a.count(False)
1
like image 3
Eric Avatar answered Oct 17 '22 12:10

Eric


Since count returns the number of items equal to its input, and since 0 is equal to False in Python, one way to approach this is to pass in something that is equal to 0 but is not equal to False.

Python itself provides no such object, but we can write one:

class Zero:
    def __eq__(self, other):
        return other == 0 and other is not False

print([1, 2, 0, False].count(Zero()))

Be aware that there are other things in Python that, like False, are equal to 0. I can think of 0.0, decimal.Decimal(0), and fractions.Fraction(0,1). Furthermore, anybody can subclass int to create other "fake 0 values", just like False. The code above counts all of these, treating False as the only special case, but you might want to do something different in your __eq__.

Of course "under the covers" this is very similar to just doing sum(other == 0 and other is not False for other in a). But considering how count() is defined, it should come as no surprise that a.count(x) is similar to sum(x == y for y in a).

You would only do this in the rare case where you have for some reason already decided to use count (perhaps because you're using some third-party code that's going to call it), and need to come up with a suitable object to pass it. Basically, it treats count as a function that calls an arbitrary function we write (requiring only that this function be the __eq__ function of the argument) and counts the number of true return values. This is an accurate description of what count does, but not really the point of count since sum is more explicit.

like image 2
Steve Jessop Avatar answered Oct 17 '22 12:10

Steve Jessop