计算Python列表中的True布尔数

问题:计算Python列表中的True布尔数

我有一个布尔值列表:

[True, True, False, False, False, True]

并且我正在寻找一种方法来计算True列表中的数目(因此,在上面的示例中,我希望返回值是3。)我已经找到了一些示例,这些示例寻找特定元素的出现次数。因为我正在使用布尔运算,所以有效的方法吗?我在想类似all或的东西any

I have a list of Booleans:

[True, True, False, False, False, True]

and I am looking for a way to count the number of True in the list (so in the example above, I want the return to be 3.) I have found examples of looking for the number of occurrences of specific elements, but is there a more efficient way to do it since I’m working with Booleans? I’m thinking of something analogous to all or any.


回答 0

True等于1

>>> sum([True, True, False, False, False, True])
3

True is equal to 1.

>>> sum([True, True, False, False, False, True])
3

回答 1

list有一个count方法:

>>> [True,True,False].count(True)
2

这实际上比效率更高sum,并且对意图更明确,因此没有理由使用sum

In [1]: import random

In [2]: x = [random.choice([True, False]) for i in range(100)]

In [3]: %timeit x.count(True)
970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit sum(x)
1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

list has a count method:

>>> [True,True,False].count(True)
2

This is actually more efficient than sum, as well as being more explicit about the intent, so there’s no reason to use sum:

In [1]: import random

In [2]: x = [random.choice([True, False]) for i in range(100)]

In [3]: %timeit x.count(True)
970 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit sum(x)
1.72 µs ± 161 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

回答 2

如果只关心常量True,那么简单sum就可以了。但是,请记住,在Python中,其他值True也会计算。一个更可靠的解决方案是使用bool内置的:

>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3

更新:这是另一个类似的健壮解决方案,具有更透明的优点:

>>> sum(1 for x in l if x)
3

PS Python琐事:True 可能不为1 可能为真。警告:请勿在工作中尝试!

>>> True = 2
>>> if True: print('true')
... 
true
>>> l = [True, True, False, True]
>>> sum(l)
6
>>> sum(bool(x) for x in l)
3
>>> sum(1 for x in l if x)
3

更多邪恶:

True = False

If you are only concerned with the constant True, a simple sum is fine. However, keep in mind that in Python other values evaluate as True as well. A more robust solution would be to use the bool builtin:

>>> l = [1, 2, True, False]
>>> sum(bool(x) for x in l)
3

UPDATE: Here’s another similarly robust solution that has the advantage of being more transparent:

>>> sum(1 for x in l if x)
3

P.S. Python trivia: True could be true without being 1. Warning: do not try this at work!

>>> True = 2
>>> if True: print('true')
... 
true
>>> l = [True, True, False, True]
>>> sum(l)
6
>>> sum(bool(x) for x in l)
3
>>> sum(1 for x in l if x)
3

Much more evil:

True = False

回答 3

您可以使用sum()

>>> sum([True, True, False, False, False, True])
3

You can use sum():

>>> sum([True, True, False, False, False, True])
3

回答 4

仅出于完整性考虑(sum通常更可取),我想提一下我们也可以filter用来获取真实值。在通常情况下,filter接受一个函数作为第一个参数,但是如果传递它None,它将为所有“真实的”值过滤。这个功能有些令人惊讶,但是有充分的文档记录,并且可以在Python 2和3中使用。

版本之间的区别在于,在Python 2中filter返回一个列表,因此我们可以使用len

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
[True, True, True]
>>> len(filter(None, bool_list))
3

但是在Python 3中,filter返回了一个迭代器,因此我们不能使用len,并且如果我们想避免使用sum(出于任何原因),我们需要求助于将迭代器转换为列表(这使它变得不那么美观了):

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

Just for completeness’ sake (sum is usually preferable), I wanted to mention that we can also use filter to get the truthy values. In the usual case, filter accepts a function as the first argument, but if you pass it None, it will filter for all “truthy” values. This feature is somewhat surprising, but is well documented and works in both Python 2 and 3.

The difference between the versions, is that in Python 2 filter returns a list, so we can use len:

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
[True, True, True]
>>> len(filter(None, bool_list))
3

But in Python 3, filter returns an iterator, so we can’t use len, and if we want to avoid using sum (for any reason) we need to resort to converting the iterator to a list (which makes this much less pretty):

>>> bool_list = [True, True, False, False, False, True]
>>> filter(None, bool_list)
<builtins.filter at 0x7f64feba5710>
>>> list(filter(None, bool_list))
[True, True, True]
>>> len(list(filter(None, bool_list)))
3

回答 5

阅读有关该问题的所有答案和评论后,我想做一个小实验。

我产生50000个随机布尔值,并呼吁sumcount他们。

这是我的结果:

>>> a = [bool(random.getrandbits(1)) for x in range(50000)]
>>> len(a)
50000
>>> a.count(False)
24884
>>> a.count(True)
25116
>>> def count_it(a):
...   curr = time.time()
...   counting = a.count(True)
...   print("Count it = " + str(time.time() - curr))
...   return counting
... 
>>> def sum_it(a):
...   curr = time.time()
...   counting = sum(a)
...   print("Sum it = " + str(time.time() - curr))
...   return counting
... 
>>> count_it(a)
Count it = 0.00121307373046875
25015
>>> sum_it(a)
Sum it = 0.004102230072021484
25015

可以肯定的是,我又重复了几次:

>>> count_it(a)
Count it = 0.0013530254364013672
25015
>>> count_it(a)
Count it = 0.0014507770538330078
25015
>>> count_it(a)
Count it = 0.0013344287872314453
25015
>>> sum_it(a)
Sum it = 0.003480195999145508
25015
>>> sum_it(a)
Sum it = 0.0035257339477539062
25015
>>> sum_it(a)
Sum it = 0.003350496292114258
25015
>>> sum_it(a)
Sum it = 0.003744363784790039
25015

如您所见,count速度比快3倍sum。因此,我建议count像在一样使用count_it

Python版本:3.6.7
CPU核心:4
RAM大小:16 GB
操作系统:Ubuntu 18.04.1 LTS

After reading all the answers and comments on this question, I thought to do a small experiment.

I generated 50,000 random booleans and called sum and count on them.

Here are my results:

>>> a = [bool(random.getrandbits(1)) for x in range(50000)]
>>> len(a)
50000
>>> a.count(False)
24884
>>> a.count(True)
25116
>>> def count_it(a):
...   curr = time.time()
...   counting = a.count(True)
...   print("Count it = " + str(time.time() - curr))
...   return counting
... 
>>> def sum_it(a):
...   curr = time.time()
...   counting = sum(a)
...   print("Sum it = " + str(time.time() - curr))
...   return counting
... 
>>> count_it(a)
Count it = 0.00121307373046875
25015
>>> sum_it(a)
Sum it = 0.004102230072021484
25015

Just to be sure, I repeated it several more times:

>>> count_it(a)
Count it = 0.0013530254364013672
25015
>>> count_it(a)
Count it = 0.0014507770538330078
25015
>>> count_it(a)
Count it = 0.0013344287872314453
25015
>>> sum_it(a)
Sum it = 0.003480195999145508
25015
>>> sum_it(a)
Sum it = 0.0035257339477539062
25015
>>> sum_it(a)
Sum it = 0.003350496292114258
25015
>>> sum_it(a)
Sum it = 0.003744363784790039
25015

And as you can see, count is 3 times faster than sum. So I would suggest to use count as I did in count_it.

Python version: 3.6.7
CPU cores: 4
RAM size: 16 GB
OS: Ubuntu 18.04.1 LTS


回答 6

首先进行比较安全bool。这很容易做到:

>>> sum(map(bool,[True, True, False, False, False, True]))
3

然后,您将在适当的存储区中捕获Python认为是或否的所有内容:

>>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
>>> list(map(bool,allTrue))
[True, True, True, True, True, True, True, True, True]

如果您愿意,可以使用一种理解:

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]

It is safer to run through bool first. This is easily done:

>>> sum(map(bool,[True, True, False, False, False, True]))
3

Then you will catch everything that Python considers True or False into the appropriate bucket:

>>> allTrue=[True, not False, True+1,'0', ' ', 1, [0], {0:0}, set([0])]
>>> list(map(bool,allTrue))
[True, True, True, True, True, True, True, True, True]

If you prefer, you can use a comprehension:

>>> allFalse=['',[],{},False,0,set(),(), not True, True-1]
>>> [bool(i) for i in allFalse]
[False, False, False, False, False, False, False, False, False]

回答 7

我更喜欢len([b for b in boollist if b is True])(或等效的generator-expression),因为它很容易解释。比伊格纳西奥·巴斯克斯(Ignacio Vazquez-Abrams)提出的答案更“神奇”。

或者,您可以执行此操作,该操作仍假定bool可转换为int,但不对True的值进行任何假设: ntrue = sum(boollist) / int(True)

I prefer len([b for b in boollist if b is True]) (or the generator-expression equivalent), as it’s quite self-explanatory. Less ‘magical’ than the answer proposed by Ignacio Vazquez-Abrams.

Alternatively, you can do this, which still assumes that bool is convertable to int, but makes no assumptions about the value of True: ntrue = sum(boollist) / int(True)