如何检查iterable中只有一个值是否解析为True?

时间:2014-04-01 23:38:03

标签: python list expression

是否有一种优雅,可读的方法来检查可迭代it中的所有元素是否解析为True(您可能会认为所有值都是布尔值,尽管这与我的问题无关)?我提出了:

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

但是我认为减少使得理解有些混乱,加上我觉得它不起作用:

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 :(得分:6)

您的标题不同意您的问题正文,但我会回答标题。

您可以sum布尔值。检查它是否等于1(或您喜欢的任何值):

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

答案 1 :(得分: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

答案 2 :(得分:0)

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

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

当然,以上只是测试x是否为布尔True,但你可以在那里进行任何比较。

你可能会说,但效率不高吗?不是真的,如果你真的想要N个项目 - 无论如何都要检查它们,看看是否还有其他True潜伏在那里。

对于'N或更多'项目的情况,您可以使用生成器(ab)来执行此操作:

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 Trues。但是在失败的情况下,只要我们看到另一个Trueany就会快捷方式,您将无法浏览列表的其余部分。