Say I have an list of values that contains some 0
s and some False
s.
Something like
arr = [0, False, False, 0, False]
How would I count each of them in Python?
list.count
doesn't work here:
>>> arr.count(0)
5
>>> arr.count(False)
5
Say I have an list of values that contains some 0
s and some False
s.
Something like
arr = [0, False, False, 0, False]
How would I count each of them in Python?
list.count
doesn't work here:
>>> arr.count(0)
5
>>> arr.count(False)
5
One option would be to use is
to compare against False
:
print(sum(1 for x in arr if x is False))
result: 3
(also works with is 0
BTW)
EDIT: we could also rely on the fact that True==1
after all: sum(x is False for x in arr)
is even simpler.
The only way to distinguish is by their type:
>>> type(False)
bool
>>> type(0)
int
But isinstance
can't be used for 0
because bool
is a subclass of int
>>> isinstance(0, bool)
False
>>> isinstance(False, int)
True
And the values are just equal (that's why count
doesn't work "correctly" for you):
>>> 0 == False
True
You could use the fact that 0
is an interned (singleton) integer in CPython (probably also other Python implementations) and False
is also a singleton:
>>> 0 is 0
True
>>> False is False
True
>>> 0 is False
False
As for a solution: Use something that isn't so equal, for example None
:
arr = [0, None, None, 0, None]
arr.count(0) # 2
arr.count(None) # 3
If you really need to use 0
and False
you could use sum
(like others have shown):
sum(x is False for x in arr) # for count(False)
sum(x is 0 for x in arr) # for count(0)
Or Python-implementation independant: the type
and value as identifier and collections.Counter
:
>>> arr = [0, False, False, 0, False]
>>> from collections import Counter
>>> Counter((type(x), x) for x in arr)
Counter({(bool, False): 3, (int, 0): 2})
This is a rare case where it seems sensible to just use a type check.
sum(1 for item in arr if item == 0 and type(item) is type(0))
As mentioned by Jean-François, if you're guaranteed to only have 0 and False
, the type check is sufficient on its own.
Here is one way using defaultdict
on order to find the count of both 0 and False at once:
In [73]: from collections import defaultdict
In [74]: d = defaultdict(int)
In [75]: for i in arr:
....: d[str(i)] += i is False or 1 # if I is not False is 0
....:
In [76]: d
Out[76]: defaultdict(<class 'int'>, {'0': 2, 'False': 3})