"and" and "or" on every item in a list

R

Raymond Hettinger

Is this the best way to test every item in a list?

def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))


alltrue(lambda x:x>1,[1,2,3])
False
alltrue(lambda x:x>=1,[1,2,3])
True

In Py2.5, you can use the builtin any() and all() functions.

In Py2.4, use the recipes from the itertools module:

def all(seq, pred=None):
"Returns True if pred(x) is true for every element in the
iterable"
for elem in ifilterfalse(pred, seq):
return False
return True

def any(seq, pred=None):
"Returns True if pred(x) is true for at least one element in the
iterable"
for elem in ifilter(pred, seq):
return True
return False

def no(seq, pred=None):
"Returns True if pred(x) is false for every element in the
iterable"
for elem in ifilter(pred, seq):
return False
return True


Raymond
 
M

Matimus

Is this the best way to test every item in a list?

def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))


alltrue(lambda x:x>1,[1,2,3])
False
alltrue(lambda x:x>=1,[1,2,3])
True

Thanks

If you are using python 2.5 the best way would be something like this:
all(x > 1 for x in [1,2,3]) False
any(x > 1 for x in [1,2,3])
True

If you are using an earlier version you are still discouraged from
using reduce in place of a more readable construct. In most cases list
comprehension is encouraged over map also.

If `all' and `any' aren't defined you can use something like the
following. One advantage of these over what you posted is that they
will return as soon as an exit condition is reached as opposed to
processing the entire list.
Code:
if not all:
 def all(seq):
  for val in seq:
   if not val:
    return False
  return True

if not any:
 def any(seq):
  for val in seq:
   if val:
    return True
  return False

Matt
 
C

Carl Banks

Is this the best way to test every item in a list?

def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))

Probably not, because it doesn't take advantage of short circuiting.
You could bail out of alltrue as soon as the first item you see is
false, but your version applies f to every item in the list. I would
suggest the most straightforear way is the best:

def alltrue(f,l):
for item in l:
if not f(item):
return False
return True


On Python 2.5, you could do this:

all(f(x) for x in l)


Carl Banks
 
P

Paul Hankin

Is this the best way to test every item in a list?

def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))

No. In Python 2.5 there are builtins 'all' and 'any' that do exactly
these. If you're using python <2.5, then you can support shortcut
evaluation - there's no need to check every element once you find a
false in 'all' or a true in 'any'.
 
T

Tim Chase

Is this the best way to test every item in a list?
def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))
alltrue(lambda x:x>1,[1,2,3]) False
alltrue(lambda x:x>=1,[1,2,3])
True

As of Python2.5, there's an any() and all() function built into
the language.
>>> any(map(lambda x: x>1, [1,2,3]))
>>> all(map(lambda x: x>1, [1,2,3]))

Implementations for older versions are given at

http://docs.python.org/lib/built-in-funcs.html

You can adjust the "if" test in the example code so that it calls
your function...something like

def my_any(f, iterable):
for element in iterable:
if f(element):
return True
return False

def my_all(f, iterable):
for element in iterable:
if not f(element):
return False
return True

The advantage of the code in the docs is that it
short-circuits...there's no need to reduce the entire list if an
early item triggers the condition (a "true" early in an "any" or
a "false" early in an "all").

While you can use a reduce(bool.__and__, thing) call, I more
frequently see it as reduce(operator.or_, thing)

Just a few ideas,

-tkc
 
D

Dustan

Is this the best way to test every item in a list?

No.

The biggest problem is, obviously, you don't take advantage of
builtins any() and all(), or write corresponding short-circuiting
versions for python versions before 2.5.

The second problem is you build an entire list that gets disposed of
just as quickly. The third problem is you use lambda, which makes your
call to map() time inefficient as well as space inefficient. Both of
these problems can be fixed by using generator expressions.
def alltrue(f,l):
return reduce(bool.__and__,map(f,l))

def onetrue(f,l):
return reduce(bool.__or__,map(f,l))


alltrue(lambda x:x>1,[1,2,3])
False
all(x>1 for x in [1,2,3])
False
alltrue(lambda x:x>=1,[1,2,3])
True
all(x>=1 for x in [1,2,3])
True

Thanks

HTH
 
G

GHZ

Thanks for the answers, I suspected something like any(), all()
existed. Also got me thinking about generator expressions, my code is
full of list comprehensions for lists I don't keep.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top