问题:计算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个随机布尔值,并呼吁sum
和count
他们。
这是我的结果:
>>> 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)