17.3 Evaluating Predicate Tests Across Sequences
Credit: Jon Dyte
17.3.1 Problem
You need to
know whether all items in a sequence satisfy a certain predicate or
if only some of them do.
17.3.2 Solution
The simplest approach for either problem is to loop on the sequence
and return a result as soon as it's known, just as
the and and or Python operators
short-circuit logical evaluation:
def every (pred, seq):
""" true if pred(x) is true for all x in seq, else false """
for x in seq:
if not pred(x): return 0
return 1
def any (pred, seq):
""" false if pred(x) is false for all x in seq, else true """
for x in seq:
if pred(x): return 1
return 0
17.3.3 Discussion
Often, it is useful to know whether all elements of a sequence meet
certain criteria or if only some do. The two functions
every
and any do just that, with the simplest, and thus
clearest, approach:
>>> every(lambda c: c > 5, (6, 7, 8, 9))
1
>>> every(lambda c: c > 5, (6, 4, 8, 9))
0
>>> any(lambda c: c > 5, (6, 7, 8, 9))
1
>>> any(lambda c: c < 5, (6, 7, 8, 9))
0
If you want to get fancy, here are two more techniques (perhaps with
some performance gain, though you shouldn't take my
word for it�always measure performance for the specific cases
you need):
def every(pred, seq): return len(seq) == len(filter(pred, seq))
def any(pred, seq): return len(filter(pred, seq))
or:
import operator
def every(pred, seq):
return reduce(operator.and_, map(pred, seq))
def any(pred, seq):
return reduce(operator.or_, map(pred, seq))
Functional forms are elegant and often fast, as long as they do not
involve a lambda.
|