如何检查可迭代对象中是否恰好有一个值为真?
有没有一种优雅且易读的方法来检查一个可迭代对象 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
。但在失败的情况下,只要我们看到另一个 True
,any
就会立即停止,这样就不会继续遍历剩下的列表了。
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