With python, I would like to run a test over an entire list, and, if all the statements are true for each item in the list, take a certain action.
Pseudo-code: If "test involving x" is true for every x in "list", then do "this".
It seems like there should be a simple way to do this.
What syntax should I use in python?
Use all(). It takes an iterable as an argument and return True if all entries evaluate to True. Example:
if all((3, True, "abc")):
print "Yes!"
You will probably need some kind of generator expression, like
if all(x > 3 for x in lst):
do_stuff()
>>> x = [True, False, True, False]
>>> all(x)
False
all() returns True if all the elements in the list are True
Similarly, any() will return True if any element is true.
Example (test all elements are greater than 0)
if all(x > 0 for x in list_of_xs):
do_something()
Above originally used a list comprehension (if all([x > 0 for x in list_of_xs]): ) which as pointed out by delnan (Thanks) a generator expression would be faster as the generator expression terminates at the first False, while this expression applies the comparison to all elements of the list.
However, be careful with generator expression like:
all(x > 0 for x in list_of_xs)
If you are using pylab (launch ipython as 'ipython -pylab'), the all function is replaced with numpy.all which doesn't process generator expressions properly.
all([x>0 for x in [3,-1,5]]) ## False
numpy.all([x>0 for x in [3,-1,5]]) ## False
all(x>0 for x in [3,-1,5]) ## False
numpy.all(x>0 for x in [3,-1,5]) ## True
I believe you want the all() method:
$ python
>>> help(all)
Help on built-in function all in module __builtin__:
all(...)
all(iterable) -> bool
Return True if bool(x) is True for all values x in the iterable.
if reduce(lambda x, y: x and involve(y), yourlist, True):
certain_action()
involve is the action you want to involve for each element in the list, yourlist is your original list, certain_action is the action you want to perform if all the statements are true.
all() alone doesn't work well if you need an extra map() phase.
see below:
all((x==0 for x in xrange(1000))
and:
all([x==0 for x in xrange(1000)])
the 2nd example will perform 1000 compare even the 2nd compare render the whole result false.
Related
Is it possible to use an if statement as an argument for another if statement ?
Like if one if statement is correct then the other if statement does this, but i'm not talking about nested ifs. Like if you have 3 if statements,
Is it possible to say if all those 3 are true then do this, or if all 3 of them are false then do this?
That's what a logical statement is for:
if condition1 and condition2 and condition3:
# do something if all three are true
else:
# not all three are true
If you have a variable number of elements to test, you could use all():
if all(conditions):
or with a generator expression:
if all(val == testvale for val in sequence_of_values):
Any of these expressions can be stored in a variable first:
list_of_conditions = [condition1, condition2, condition3]
if some_fourth_condition and all(list_of_conditions):
but then you lose the short-circuiting behaviour of the and operand; all 3 condition expressions will be evaluated to build list_of_conditions, while and won't evaluate the right-hand expression if the left-hand expression resolved to a false value.
Last, but not least, there is the conditional expression, which returns the outcome of one of two expressions based on an boolean test:
outcome = true_expression if test_expression else false_expression
and only one of true_expression or false_expression will actually be evaluated based on the outcome of test_expression.
I think you mean and:
if <condition1> and <condition2> and <condition3>:
# All three conditions were True
elif not <condition1> and not <condition2> and not <condition3>:
# All three conditions were False
Of course, you could also use all and any:
if all((<condition1>, <condition2>, <condition3>)):
# All three conditions were True
elif not any((<condition1>, <condition2>, <condition3>)):
# All three conditions were False
Maybe this would be useful for you:
x = 1
y = 2
z = 3
my_function(x if x > z else y) # function called with y
x = 4
my_function(x if x > z else y) # function called with x
It can of course be combined with all() and any() as described by others.
Can anyone help me understand why the following Python script returns True?
x = ''
y = all(i == ' ' for i in x)
print(y)
I imagine it's something to do with x being a zero-length entity, but cannot fully comprehend.
all() always returns True unless there is an element in the sequence that is False.
Your loop produces 0 items, so True is returned.
This is documented:
Return True if all elements of the iterable are true (or if the iterable is empty).
Emphasis mine.
Similarly, any() will always return False, unless an element in the sequence is True, so for empty sequences, any() returns the default:
>>> any(True for _ in '')
False
As the documentation states, what all does is:
Return True if all elements of the iterable are true (or if the iterable is empty).
How would I find if I have a list of a given string, 'hello':
x = ['hello', 'hello', 'hello']
# evaluates to True
x = ['hello', '1']
# evaluates to False
Use the all() function to test if a condition holds True for all elements:
all(el == 'hello' for el in x)
The all() function takes an iterable (something that produces results one by one) and will only return True itself if all those elements are true. The moment it finds anything that is false, it'll return False and not look further.
Here the iterable is a generator expression, one that executes an equality test for each element in the input sequence. The fact that all() stops iterating early if a false value is encountered makes this test very efficient if the test in the contained generator expression is False for any element early on.
Note that if x is empty, then all() returns True as well as it won't find any elements that are false in an empty sequence. You could test for the sequence being non-empty first:
if x and all(el == 'hello' for el in x):
to work around that.
This ought to work:
# First check to make sure 'x' isn't empty, then use the 'all' built-in
if x and all(y=='hello' for y in x):
Nice thing about the all built-in is that it stops on the first item it finds that doesn't meet the condition. This means it is quite efficient with large lists.
Also, if all of the items in the list are strings, then you can use the lower method of a string to match things like `'HellO', 'hELLO', etc.
if x and all(y.lower()=='hello' for y in x):
Yet another way to do what you want (all is the most idiomatic way to do that, as all other answers note), useful in case if you need to check more than once:
s = set(l)
cond = (len(s) == 1) and (item in s)
It helps to avoid O(n) traversal every time you want to check the condition.
Using filter and len is easy.
x = ['hello', 'hello', 'hello']
s = 'hello'
print len(filter(lambda i:i==s, x))==len(x)
Youn can do that using set:
set(x) == {'hello'}
Can anybody explain why in python builtin buinction all return True in this case all([])?
In [33]: all([])
Out[33]: True
In [34]: all([0])
Out[34]: False
In [35]: __builtins__.all([])
Out[35]: True
I'm not convinced that any of the other answers have really address the question of why this should be the case.
The definition for Python's all() comes from boolean logic. If for example we say that "all swans are white" then a single black swan disproves the statement. However, if we say that "all unicorns are pink" logicians would take that as a true statement simply because there are no non-pink unicorns. Or in other words "all " is vacuously true.
Practically it gives us a useful invariant. If all(A) and all(B) are both true then the combination of all(A + B) is also true. If all({}) was false we should have a less useful situation because combining two expressions one of which is false suddenly gives an unexpected true result.
So Python takes all([]) == True from boolean logic, and for consistency with other languages with a similar construct.
Taking that back into Python, in many cases the vacuous truth makes algorithms simpler. For example, if we have a tree and want to validate all of the nodes we might say a node is valid if it meets some conditions and all of its children are valid. With the alternative definition of all() this becomes more complex as we have to say it is valid if it meets the conditions and either has no children or all its children are valid.
class Node:
def isValid(self):
return some_condition(self) and all(child.isValid for child in self.children)
From the docs:
Return True if all elements of the iterable are true (or if the iterable is empty).
So, roughly, it's simply defined this way.
You can get around that by using
list = []
if list and all(list):
pass
As the docs say, all is equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
For an empty iterable the loop body is never executed, so True is immediately returned.
Another explanation for this is that all and any are generalisations of the binary operators and and or for arbitrarily long numbers of parameters. Thus, all and any can be defined as:
def all(xs):
return reduce(lambda x,y: x and y, xs, True)
def any(xs):
return reduce(lambda x,y: x or y, xs, False)
The True and False parameters show that all([]) == True and any([]) == False.
Any expression with all can be rewritten by any and vice versa:
not all(iterable)
# is the same as:
any(not x for x in iterable)
and symmetrically
not any(iterable)
# is the same as:
all(not x for x in iterable)
These rules require that all([]) == True.
The function all is very useful for readable asserts:
assert all(required_condition(x) for x in some_results_being_verified)
(It is not so bad if a task has no results, but something is very broken if any result is incorrect.)
I have lots of small pieces of code that look like:
for it in <iterable>:
if <condition>:
return True/False
Is there a way I can rewrite this piece of code with a lambda expression ? I know I can factor it out in a small method/function, but I am looking for some lambda thing if it can be done.
Use the built-in any function.
e.g.
any(<condition> for it in <iterable>) # return True on <condition>
In addition to what everyone else has said, for the reverse case:
for it in <iterable>:
if <condition>:
return False
return True
use all():
b = all(<condition> for it in <iterable>)
if you want to check the condition for every item of iterable you can use
listcomprehensions to to this
b = [ x == whatever for x in a ]
you can combine this with any if you only need to know if there is one element
that evals to true for your condition
b = any(x == whatever for x in a)
Here is a simple example which returns True if any of the objects in it is equal to 2. by using the map function:
any(map(lambda x: x==2, it))
Change the lambda expression to reflect your condition.
Another nice way is to use any with a list comprehension:
any([True for x in it if x==2])
or alternatively, a generator expression:
any(x==2 for x in it)