andmap and ormap

Scott David Daniels scott.daniels at acm.org
Tue Mar 14 18:11:28 EST 2006


wkehowski at cox.net wrote:
> The following works perfectly:
> import operator
> def andmap(b,L):
>     return reduce(operator.and_, [b(x) for x in L])
> def ormap(b,L):
>     return reduce(operator.or_, [b(x) for x in L]) 

Note your [b(x) for x in L] evaluates b(x) for all elements of L
before you begin the analysis.
In 2.3 and beyond, you could define:

     def imap(function, source):
         for element in source:
             yield function(element)

And apply any or all (as defined below) to imap(b, L)

Although, you often needn't use bool(expr) in Python, more things are
reasonable to use directly as tests; if implicitly converts to bool.
So, for those cases, you could simply use any(L) or all(L).

If you wish to use any and all (coming in 2.5), you could go with:

def any(iterable):
     '''True iff at least one element of the iterable is True'''
     for element in iterable:
	if element:
	    return True # or element and change the definition
     return False

def all(iterable):
     '''True iff no element of the iterable is True'''
     for element in iterable:
	if not element:
	    return False
     return True

These will short-circuit in 2.3 and up (where iterators live).
In 2.4 and up, generator expressions can be used:

     any(x*7-4 > 100 for x in xrange(50))

Even in 2.3, any and all as defined above work with generators:

     def generates(limit):
         for i in xrange(limit):
             yield i * 7 - 4 > 100

     any(generates(800000000))
True
     any(generates(8))
False

--Scott David Daniels
scott.daniels at acm.org



More information about the Python-list mailing list