Imagine you need to count number of iterable
elements that satisfy some criteria
- is there is a more good looking way to do this?
It's python3 of course. But 2 is fine too.
I can't find anything suitable in collections
or itertools
python modules or in built-ins.
Try the quantify
recipe from itertools
recipes:
def quantify(iterable, pred=bool):
"Count how many times the predicate is true"
return sum(map(pred, iterable))
more_itertools
already implements this recipe, so it is even more compact:
>>> import more_itertools as mit
>>> iterable = [True, False, True, True]
>>> mit.quantify(iterable)
3
For comparison:
>>> #len(list(filter(lambda x: criteria, iterable)))
>>> len(list(filter(lambda x: x is True, iterable)))
3
Performance
# A: len(list(filter(lambda x: criteria, iterable)))
>>> %timeit -n 1000000 len(list(filter(lambda i: i is True, iterable)))
1000000 loops, best of 3: 2.48 µs per loop
# B: quantify(iterable, pred=condition)
>>> %timeit -n 1000000 mit.quantify(iterable)
1000000 loops, best of 3: 1.87 µs per loop
# C: ilen(item for item in iterable if condition)
>>> %timeit -n 1000000 mit.ilen(i for i in iterable if i is True)
1000000 loops, best of 3: 5.27 µs per loop
# D: len([item for item in iterable if condition])
>>> %timeit -n 1000000 len([i for i in iterable if i is True])
1000000 loops, best of 3: 973 ns per loop
# E: sum(1 for _ in iterable if condition)
>>> %timeit -n 1000000 sum(1 for i in iterable if i is True)
1000000 loops, best of 3: 1.34 µs per loop
quantify
, itertools
recipe more_itertools.ilen
to evaluatesum(1 for _ in ...)
idiomWhile more_itertools.quantify
is concise, the idiomic generator expression is on par if not faster. However, classic list comprehensions (first suggested by @宏杰李) are the best performers.
See also a thread on extending len()
to generators.
sum(1 for i in A if condition(i))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With