如何检查可迭代对象中是否恰好有一个值为真?

3 投票
3 回答
1511 浏览
提问于 2025-04-18 00:56

有没有一种优雅且易读的方法来检查一个可迭代对象 it 中的所有元素是否都为 True(你可以假设所有值都是布尔值,虽然这和我的问题无关)?我想出了这个方法:

any(it) and not reduce(lambda x, y: x and y, it)

但我觉得这个 reduce 让人有点困惑,而且我觉得它并不管用:

In [1]: a=[True, True, False]

In [7]: any(a) and not reduce(lambda x, y: x and y, a)
Out[7]: True

有没有更容易理解的方法呢?

更新:我意识到我上面表达的错误。reduce() 需要在看到一个 True 时就 停止,而不是继续。

3 个回答

0

所以,这个一般的格式大概是这样的:

test = [True, True, False]
if len([x for x in test if x]) == 1:
    # Do something

当然,上面的代码只是用来测试 x 是否是布尔值 True,你可以在这里放任何类型的比较。

你可能会问,这样做不是效率低下吗?其实不是,如果你真的想要正好 N 个项目,你还是得检查所有的项目,看看里面有没有其他的 True

对于 'N 或更多' 项目的情况,你可以稍微(滥用一下)生成器来实现:

from itertools import islice
result = True
g = (x for x in test if x)
if len(list(islice(g, 2))) == 2: 
    # do something    

这有点像是个捷径,因为它会在看到足够数量的项目后就停止,不会继续遍历生成器。如果你想用这种方式来精确计数,它比列表的方式有一点小优势:

if len(list(islice(g, 2))) == 2 and not any(g):
    # do something 

为什么会有小优势呢?在通过的情况下,我们仍然需要查看每一个项目,以确保列表中正好有 2 个 True。但在失败的情况下,只要我们看到另一个 Trueany 就会立即停止,这样就不会继续遍历剩下的列表了。

5

你可以使用 count 来实现这个功能:

>>> a=[True, True, False]
>>> if a.count(True) == 1:
...     print 'Hello'
... else:
...     print 'Sorry'
Sorry

示例

>>> [True, False].count(True) == 1
True

>>> [True, True, False].count(True) == 1
False

>>> [True, True, False].count(False) == 1
True
9

你的标题和问题的内容不太一致,不过我还是会根据标题来回答。

你可以对布尔值(也就是真和假)进行求和。你可以检查一下这个和是否等于1(或者你想要的其他值):

>>> a = [True, True, False]
>>> sum(a)
2
>>> b = ['hey', '', 'a string']
>>> sum(map(bool,b))
2

撰写回答