57

Is there a good, succinct/built-in way to see if all the values in an iterable are zeros? Right now I am using all() with a little list comprehension, but (to me) it seems like there should be a more expressive method. I'd view this as somewhat equivalent to a memcmp() in C.

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'

I would expect a built-in function that does something like:

def allcmp(iter, value) :
    for item in iter :
        if item != value :
            return False
    return True

Does that function exist in python and I'm just blind, or should I just stick with my original version?

Update

I'm not suggesting that allcmp() is the solution. It is an example of what I think might be more meaningful. This isn't the place where I would suggest new built-ins for Python.

In my opinion, all() isn't that meaningful. It doesn't express what "all" is checking for. You could assume that all() takes an iterable, but it doesn't express what the function is looking for (an iterable of bools that tests all of them for True). What I'm asking for is some function like my allcmp() that takes two parameters: an iterable and a comparison value. I'm asking if there is a built-in function that does something similar to my made up allcmp().

I called mine allcmp() because of my C background and memcmp(), the name of my made up function is irrelevant here.

Community
  • 1
  • 1
mjschultz
  • 1,936
  • 1
  • 18
  • 20
  • 12
    **More** Expressive?!?! `all([ v == 0 for v in values ])` is really very, very nice, clear, explicit and expressive. How much better could it be? – S.Lott Aug 19 '10 at 20:36
  • Hmmm, perhaps I should have said more meaningful. It might be because I am still somewhat new to Python, but to me that line would take a little time to decipher. However, `if itercmp(values, 0)` seems more meaningful because I'd know quickly that I am comparing all values with 0. Might just be my C background doing that though... – mjschultz Aug 19 '10 at 22:05
  • @mjschultz: "... I am comparing all values with 0" -- how do you know "all"? "iter" doesn't mean "all". Comparing with what purpose? Check if any zeroes? Check if all zeroes? Count the zeroes? – John Machin Aug 19 '10 at 22:17
  • @ mjschultz: `itercmp(values, 0)` more "meaningful" than `all([ v == 0 for v in values ])`. What? How is that possible? Please **update** your question with an explanation of how `itercmp` is somehow more expressive than `all()` and `0` is more expressive than `v == 0`. I assume you're not kidding, so please **update** the question with an explanation of how this is an improvement. – S.Lott Aug 20 '10 at 10:13
  • 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? – S.Lott Aug 20 '10 at 14:23
  • No, that would be stupid. `alltrue()` would suffice, all would imply an iterable and true implies the test. What I'm looking for is a general function that can test for more than just true. I'll assume from your sarcastic answer that you don't know of one. – mjschultz Aug 20 '10 at 15:42
  • @ mjschultz: Sarcasm? I don't think so. I'm trying to actually understand your question. Since `all` seems to be perfectly descriptive, I cannot understand your complaint. Still. So `allTrue` would be better than `all`? Is that what you're saying? What is this "general function" that tests for more than True. True/False is the result of **all** possible comparison operators, so `all` applies to **all** possible logical tests. What are you asking for? – S.Lott Aug 20 '10 at 19:29
  • I'm saying that `all()` is *not* perfectly descriptive. `all(list)` doesn't mean anything and may or may not be correct, `alltrue(list)` tells me that we are looking to see if all values in `list` are true. A general function would be `all(list, True)` meaning that all items in `list` are `True` or `all(list, 0)` meaning that all items in `list` are `0` or `all(list, 'ok')` meaning that all items in `list` are `'ok'`. The question is: "Is there a good, succinct/built-in way to see if all the values in an iterable are zeros?" I'm not sure where your confusion lies here. – mjschultz Aug 20 '10 at 23:52
  • @mjschultz: My confusion is simple. Given a single clear, simple, general function that can be applied to **all** possible predicates, you seem to be asking for a function that applies to only **one** specific predicate, `==`. It doesn't seem sensible to ask for a function that applies to only **one** predicate when Python already has a function that already applies to **all** possible predicates. I don't get the "please limit me to just one special-purpose predicate" behind the question. What's the value in the limitation? – S.Lott Aug 21 '10 at 03:05
  • I believe `all()` only applies to "is true" predicate, you need to contort all the items in the list to have a truth value using a generator, which has the multiple predicate you are talking about. I am okay with using the generator, but I was asking if there is a way to express it without the generator. There is, in fact, a way to do that using numpy.array(), which probably build the generator automatically as part of `__cmp__`. – mjschultz Aug 21 '10 at 14:28
  • Please read edits to my answer. – Tomasz Wysocki Jun 11 '12 at 06:35
  • any() seems to do this when used along with a 'not'. – xax Sep 13 '22 at 12:29

6 Answers6

117

Use generators rather than lists in cases like that:

all(v == 0 for v in values)

Edit:

all is standard Python built-in. If you want to be efficient Python programmer you should know probably more than half of them (http://docs.python.org/library/functions.html). Arguing that alltrue is better name than all is like arguing that C while should be call whiletrue. Is subjective, but i think that most of the people prefer shorter names for built-ins. This is because you should know what they do anyway, and you have to type them a lot.

Using generators is better than using numpy because generators have more elegant syntax. numpy may be faster, but you will benefit only in rare cases (generators like showed are fast, you will benefit only if this code is bottleneck in your program).

You probably can't expect nothing more descriptive from Python.

PS. Here is code if you do this in memcpm style (I like all version more, but maybe you will like this one):

list(l) == [0] * len(l)
Tomasz Wysocki
  • 11,170
  • 6
  • 47
  • 62
26

If you know that the iterable will contain only integers then you can just do this:

if not any(values):
    # etc...
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • That is shorter, but I think it conceals the meaning behind what it does even more since it depends on values being `== 0`. – mjschultz Aug 19 '10 at 22:01
  • 3
    -1 By the time you have heavily commented the code so that it can be understood by non-sophists, you might as well have written 'all(v == 0 for v in values)` which is self-explanatory and future proof (when you decide that it should have been some integer other than zero). – John Machin Aug 19 '10 at 23:54
  • 2
    code practices subjectivity aside, `if not any` is correct English as it is readable code. Furthermore, in certain applications like physics, where 0 is objectively known as "at rest" or "off", then this code is just as maintainable as it is readable. – ecoe Dec 11 '15 at 03:43
8

If values is a numpy array you can write

import numpy as np
values = np.array((0, 0, 0, 0, 0))
all(values == 0)
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • That `all` line is precisely as expressive and meaningful as I want. I just wish it didn't rely on numpy. :( – mjschultz Aug 20 '10 at 17:22
8

The any() function may be the most simple and easy way to achieve just that. If the iterable is empty,e.g. all elements are zero, it will return False.

values = (0, 0, 0, 0, 0)
print (any(values)) # return False
Harry
  • 1,147
  • 13
  • 13
  • 1
    suggested to use `any()` instead of `all()` in consideration of (worst case) time scaling iterations - good answer. – Elysiumplain May 24 '21 at 18:49
3

The built-in set is given an iterable and returns a collection (set) of unique values.

So it can be used here as:

set(it) == {0}
  • assuming it is the iterable
  • {0} is a set containing only zero

More info on python set-types-set-frozenset here in docs.

ZF007
  • 3,708
  • 8
  • 29
  • 48
Bloop93
  • 31
  • 3
2

I prefer using negation:

all(not v for v in values)
Nic Scozzaro
  • 6,651
  • 3
  • 42
  • 46