Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python's shortcut for len(list(filter(lambda x: criteria, iterable)))

Tags:

python

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.

like image 569
scythargon Avatar asked Dec 16 '16 01:12

scythargon


2 Answers

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
  • A: control - author's example
  • B: faster - quantify, itertools recipe
  • C: slowest - generator expression, uses more_itertools.ilen to evaluate
  • D: fastest - list comprehension
  • E: faster - generator expression, sum(1 for _ in ...) idiom

While 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.

like image 152
pylang Avatar answered Nov 15 '22 03:11

pylang


sum(1 for i in A if condition(i))
like image 41
DaveQ Avatar answered Nov 15 '22 05:11

DaveQ