I l@ve RuBoard Previous Section Next Section

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.

    I l@ve RuBoard Previous Section Next Section