2

I am trying to find out if there are any built-in tools in Python that work the same way any() and all() are implemented, but instead of checking if each element is truthy or falsy, you can pass your own boolean-evaluating function or lambda, sort of like you can do with the map() function.

So what I'm asking is if there are any built-in functions where you could do something like:

from random import randint
lst = [randint(1, 100) for _ in range(1000000)]
has_even = any(lambda x: not x % 2, lst)

or

has_even = any(has_even_fn, lst)

where has_even_fn would be a function that checked if an integer is even.

You can still use any() to check if lst has evens:

has_even = any([not x % 2 for x in lst])

But of course this is strictly O(n) because the entire boolean list has to be built first, while the function I am asking for would only be O(n) in the worst case, and potentially O(1) in the best case.

dabadaba
  • 9,064
  • 21
  • 85
  • 155
  • 5
    Just remove the `[]` in `all` or `any` so the list comprehension will be turned to a generator expression. This includes some overhead but it doesn't eagerly transform the complete list. – MSeifert Dec 19 '16 at 14:14
  • 1
    "But of course this is strictly O(n) because the entire boolean list has to be built first" That's because you chose to use a list comprehension here. You can just use a generator expression instead: `any(not x % 2 for x in lst)` – Vincent Savard Dec 19 '16 at 14:15
  • You can also just use `map`. `any(map(lambda x: not x%2, lst))` – Patrick Haugh Dec 19 '16 at 14:16
  • @PatrickHaugh Only in Python 3. With py2 one needs to use `itertools.imap`. – MSeifert Dec 19 '16 at 14:16
  • I will accept any of the generation expression comments as answers, they're exactly what I was looking for. A shame I neglected generator expressions. – dabadaba Dec 19 '16 at 14:17

1 Answers1

2

As already stated in the comments, you can just remove the [ ] to get a lazy-evaluating generator expression instead of an eager list comprehension:

contains_one_or_more_even = any(x % 2 == 0 for x in lst)

or

contains_only_even = all(x % 2 == 0 for x in lst)
MSeifert
  • 145,886
  • 38
  • 333
  • 352