计算Python列表中的True布尔数


152

我有一个布尔值列表:

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

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


就像您还记得如何仅使用汇编程序在硬件中完成位计数一样。
Vladislavs Dovgalecs

Answers:



152

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)

2
如果也有0值,我就无法计算False值
Kostanos

10
sum如果您除了1或True之外还有其他“ true”值,则不能使用其他答案。此外,然后问题只剩下Trueor False
Mark Tolonen '17

43

如果只关心常量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

好的,我看到了您的示例,并且看到了它在做什么。除了它的笑声,实际上是否有充分的理由要做您在这里显示的内容?
acs 2012年

1
是的,顶部。正如我指出的那样,Python测试“ true”(如if语句中所示)比仅仅测试更为复杂True。请参阅docs.python.org/py3k/library/stdtypes.html#truth。该True = 2只是为了强化这种“真”的概念比较复杂; 加上一点点额外的代码(即使用bool()),您就可以使解决方案更强大,更通用。
内德·迪利

9
在Python 3中,TrueFalse是关键字,您不能更改它们。
ThePiercingPrince

8

您可以使用sum()

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

5

仅出于完整性考虑(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

4

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

我产生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


3

首先进行比较安全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]

1

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

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


您的解决方案至少有两个问题。第一,它具有相同的鲁棒性问题。只需将测试更改为即可解决 if b。但是,更重要的是,您正在构造一个一次性清单,要求所有值都立即存储在内存中,并且不能len与生成器表达式一起使用。最好避免这种做法,以便解决方案可以扩展。
内德·迪利

@Ned Deily:if b完全错误。仅当问题与评估为True而不是实际True布尔值有关的问题时才是正确的。不过,我同意你的第二点。在这种情况下,存在变体sum(1 if b is True else 0 for b in boollist)
kampu 2012年

正如我在其他地方指出的那样,对于这个问题,我还是不清楚OP是否真正意味着仅对值为1的bool类型的对象进行计数还是意味着对值进行评估的更大且通常更有用的一组值。如果是前者,那么身份测试是正确的方法,但它也是有限的。无论如何,布尔类型的对象在Python中还是比较奇怪的鸭子,这是该语言中相对较新的功能。无论如何,我都会更简单一些:sum(1 for b in boollist if b is True)
Ned Deily 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.