检查可迭代对象中的所有值是否都为零

60
有没有一种好的、简明/内置的方法可以查看可迭代对象中的所有值是否都为零?目前,我正在使用带有小列表推导式的all(),但是(对我来说)似乎应该有一种更具表现力的方法。我认为这有点类似于C语言中的memcmp()
values = (0, 0, 0, 0, 0)
# Test if all items in values tuple are zero
if all([ v == 0 for v in values ]) :
    print 'indeed they are'
我会期望有一个内置函数能够执行以下操作:
def allcmp(iter, value) :
    for item in iter :
        if item != value :
            return False
    return True

这个函数在Python中是否存在,还是我视力有问题?或者我应该坚持使用原版?

更新

我并不建议使用all()作为解决方案。它只是一个我认为可能更有意义的例子。这不是我建议为Python创建新内置函数的地方。

在我看来,all()并没有那么有意义。它没有表达出“全部”正在检查什么。你可以假设all()接受一个可迭代对象,但它并没有表达出这个函数正在寻找什么(一个由布尔值组成的可迭代对象,测试它们是否全部为True)。我想要的是类似于我的allcmp()的某个函数,它接受两个参数:一个可迭代对象和一个比较值。我想知道是否有类似于我虚构的allcmp()的内置函数。

我将它称为allcmp()是因为我有C语言的背景和memcmp()这个虚构函数的名称在这里并不重要


12
“更”有表现力?!?! all([v == 0 for v in values]) 确实非常好,清晰明确且富有表现力。它还能更好吗? - S.Lott
@mjschultz: "...我正在将所有值与0进行比较"--你怎么知道"所有"? "iter"并不意味着"所有". 比较的目的是什么? 检查是否有零? 检查是否全部为零? 计算零的数量? - John Machin
1
"all() ... doesn't express what "all" means"? Can't see the point you're trying to make. Do you want all to be spelled "takes_an_iterable_of_bools_and_tests_all_of_them_for_True"? Is that what you're asking for?" “all()…不表达'all'的含义”?我看不出你想要表达什么。你是想让all被拼写为“takes_an_iterable_of_bools_and_tests_all_of_them_for_True”吗?这是你想要的吗? - S.Lott
请阅读我答案的修改。 - Tomasz Wysocki
当与“not”一起使用时,any()似乎会执行此操作。 - xax
显示剩余7条评论
6个回答

120

在这种情况下,使用生成器而不是列表:

all(v == 0 for v in values)

编辑:

all 是标准 Python 内置函数。如果你想成为高效的 Python 程序员,你应该了解其中大约一半以上的函数 (http://docs.python.org/library/functions.html)。争论使用 alltrue 比使用 all 更好是像争论 C 语言的 while 应该被称为 whiletrue 一样主观。但我认为大多数人更喜欢内置函数名称更短的形式。这是因为无论如何你都应该知道它们的作用,并且你会经常使用它们。

相比于 numpy,使用生成器有更简洁的语法。numpy 可能更快,但只有在极少数情况下才会有所帮助(像所示的生成器很快,只有在你的程序中这段代码成为瓶颈时才会有所帮助)。

你可能不能期望从 Python 中获得更多描述性的信息。

附:如果你使用 memcpm 风格的代码(我更喜欢所有版本,但也许你会喜欢这个版本):

list(l) == [0] * len(l)

有趣,我之前不知道生成器,感谢您的提示。 - mjschultz
它似乎相当直接地表达了您的意图。 - bukzor
1
有没有更快的处理字节串/字节数组的方法? - ivan_pozdeev

27

如果您知道可迭代对象仅包含整数,则可以这样做:

if not any(values):
    # etc...

这段代码更短,但我认为它更加隐晦,因为它依赖于值为== 0 - mjschultz
3
当你在代码中添加大量注释以便为非哲学家所理解时,与其如此,还不如直接编写'all(v == 0 for v in values)`,这是不言自明的且具备未来性(当你决定它应该是其他整数而不是零时)。 - John Machin
2
编程实践中的主观性可以放在一边,if not any 是正确的英语,因为它是可读的代码。此外,在某些应用程序中,比如物理学中,0 被客观地认为是“静止”或“关闭”,那么这段代码既易于维护又易于阅读。 - ecoe

9

any()函数可能是最简单和最容易实现这一目标的方式。如果可迭代对象为空,例如所有元素都为零,则它将返回False。

values = (0, 0, 0, 0, 0)
print (any(values)) # return False

1
建议在考虑(最坏情况下)时间缩放迭代时使用any()而不是all() - 很好的答案。 - Elysiumplain

8
如果values是一个numpy数组,你可以写成:
import numpy as np
values = np.array((0, 0, 0, 0, 0))
all(values == 0)

那个 all 行正是我想要的表达和意义。只是我希望它不要依赖于 numpy。 :( - mjschultz

3

内置的set函数接受一个可迭代对象并返回一个唯一值的集合(集合中不含重复元素)。

因此,可以将其用于以下情况:

set(it) == {0}
  • 假设it是可迭代的
  • {0}是仅包含零的集合

有关Python set-types-set-frozenset的更多信息请参阅此处


最初的回答:

良好地使用数据类型内置函数,但请记住这将丢失索引 - 如果这很重要。 - Elysiumplain

2

我更喜欢使用否定:

all(not v for v in values)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接