 LoicM -4 years ago 77
Python Question

# clever any() like function to check if at least n elements are True?

Say I have an iterable (in my case a list):

``````l = [True, False, False, True]
``````

I know that the easiest and fastest way to check if at least one of those elements is True is simply to use
`any(l)`
, which will return
`True`
.

But what if I want to check that at least two elements are
`True`
?
My goal is to process it in the fastest way possible.

My code right now looks like this (for two elements):

``````def check_filter(l):
if len([i for i in filter(None, l)]) > 1:
return True
return False
``````

This is about 10 times slower than
`any()`
, and does not seem very pythonic to me. MSeifert

You could simply use an iterator over the sequence and check that `any` on the iterator returns always True for `n`-times:

``````def check(it, num):
it = iter(it)
return all(any(it) for _ in range(num))

>>> check([1, 1, 0], 2)
True

>>> check([1, 1, 0], 3)
False
``````

The key point here is that an iterator remembers the position it was last so each `any` call will start where the last one ended. And wrapping it in `all` makes sure it exits early as soon as one `any` is `False`.

At least performance-wise this should be faster than most other approaches. However at the cost of readability.

If you want to have it even faster than a solution based on `map` and `itertools.repeat` can be slightly faster:

``````from itertools import repeat

def check_map(it, num):
return all(map(any, repeat(iter(it), num)))
``````

``````# Second "True" element is in the last place
lst =  + *1000 + 

%timeit check_map(lst, 2)  # 10000 loops, best of 3: 20.3 µs per loop
%timeit check(lst, 2)      # 10000 loops, best of 3: 23.5 µs per loop
%timeit many(lst, 2)       # 10000 loops, best of 3: 153 µs per loop
%timeit sum(l) >= 2        # 100000 loops, best of 3: 19.6 µs per loop

# Second "True" element is the second item in the iterable
lst = [1, 1] + *1000

%timeit check_map(lst, 2)  # 100000 loops, best of 3: 3.05 µs per loop
%timeit check(lst, 2)      # 100000 loops, best of 3: 6.39 µs per loop
%timeit many(lst, 2)       # 100000 loops, best of 3: 5.02 µs per loop
%timeit sum(lst) >= 2      # 10000 loops, best of 3: 19.5 µs per loop
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download