If statement where if 3 of 5 conditions are true in Python - python

I was wondering how to have an if statement in python that will react to any 3 out of 5 conditions being true to make the if statement true.
if (a>2) and (b>3) and (c>2) and (d>6) and (e>4):
list.append(True)
This code would add true to the array "list" if all 5 conditions are met but I was wondering how to get it to work if any 3 of the 5 are true to then append true to "list"?

How about this?
values = [a>2, b>3, c>2, d>6, e>4]
if sum(values) >= 3:
list.append(True)
Just copying what #Blckknght said in the comments b/c I can't explain it better. This works because:
True is equal to 1 and False is equal to 0 (the bool class is a subclass of int)
sum sums numbers, so you check for a sum of booleans >= 3!

Similar to #Tom 's answer but with using tuples that leads to (maybe) faster construction, garbage collection and (maybe) a nicer syntax.
if sum((a > 2, b > 3, c > 2, d > 6, e > 4)) >= 3:
lst.append(True)

Related

One liner with nested if/else conditions

Real python noob here, and I'm a bit puzzled by looking at the result of this nested if/else one-liner:
>>> num_arr = [5, 10, 15]
>>> [i**2 if i == 10 else i-5 if i < 7 else i+5 for i in num_arr]
[0, 100, 20]
Shouldn't the result be [0, 15, 20] since 10 is greater than 7?
As I mentioned in the comments, the "correct" version (note the parentheses) is:
[(i**2 if i == 10 else i-5) if i < 7 else i+5 for i in num_arr]
Your "problem" stems from the chaining of your if statements, which execute in the English reading order (left to right). So it reads like this:
[i**2 if i == 10 else (i-5 if i < 7 else i+5) for i in num_arr]
where i=5, i != 10 in the "first expression", so you move to else; where i < 7 so you get i-5, or 0
where i=10, i == 10 so you get i**2, or 100
where i=15, i != 10 so you move to else, where i is not less than 7, so you get i+5, or 20
From the documentation:
To make the semantics very clear, a list comprehension is equivalent to the following Python code:
for expr1 in sequence1:
for expr2 in sequence2:
...
for exprN in sequenceN:
if (condition):
# Append the value of
# the expression to the
# resulting list.
That means yours looks like:
[[expr1] if [condition] else [[expr2] if [condition] else [expr3]] for ...]
Here's the expanded version of the one liner:
for i in num_arr:
if i == 10:
i ** 2
else:
if i < 7:
i - 5
else:
i + 5
The one-liner if statement is basically: [action] if [condition] else [action]. In other words, do this if said condition is met. Otherwise, do this action.
It's a reason I don't like one-liners is because they become less Pythonic. The code above is more verbose but it's easier to understand.
The value if the condition is True is stated before the if and the value if False is after the else (see https://docs.python.org/2.5/whatsnew/pep-308.html).
Result is i-5 for 5 because i is not 10 but it is < 7
Result is i ** 2 for 10 because i == 10
Result is i + 5 for 15 because i is not 10 and it is not < 7
Hence [0, 100, 20]

While loop and logical operators in Python - how does it work?

Why is it that when I type the code:
A = 0
B = 0
while A<10 or B<5:
A+=1
B+=1
print(A)
print(B)
the loop doesn't stop when B=5; instead, it continues to add 1 to both A and B until A = 10, then it stops. The same thing happens when I swap the order, like:
while B<5 or A<10:
When I replaced 'or' with 'and', the code stops when B=5, just the way I wanted. I'm just confused as to how 'or' and 'and' actually works.
It's similar to English:
or gives True when any of the conditions on both sides are True.
and gives True when all of the conditions on both sides are True.
A < 10 and B < 5 means that your loop while continue while A is less than 10 AND B is less than 5 (checking both conditions) or in other words, it will only stop if when A has a value more than or equal to 10 OR B has a value that is more than or equal to 5 (any one of the two).
As for A < 10 or B < 5, the loop will continue if A has a value that is less than 10 OR B has a value that is less than 5 (any one of the two). That is, if A = 10 and B = 2 the loop will still continue because B still fulfills the condition. The loop will only terminate if A has a value that is more than or equal to 10 AND B has a value that is more than or equal to 5 (the two has to be true).

Best method to get variable that does not equal a count function parameter?

I am using the count function to check if exactly 2 out of 3 variables are equal to a number. After the function is called, is there an easier or better way to find the variable that did not equal the number in the count function than what I did below? I am looking for a pure Python solution without packages.
This is what I am currently using to get the variable that does not equal the count function parameter:
num1 = 5
num2 = 7
num3 = 5
list = [num1, num2, num3]
if list.count(5) == 2:
for e in list:
if e != 5:
print(e)
I am using Python 3.7
I'm not sure if this counts as "easier", but it's certainly shorter to do this:
list = [5,7,5]
[x for x in list if x != 5]
I would suggest using numpy's vectorized operations, which are fast and very intuitive.
import numpy as np
a = np.array([5,7,10])
Then
>>> a == 5
array([ True, False, False])
>>> (a == 5).sum() # how many are equal to 5?
1
>>> a[a!=5]
array([ 7, 10])
Of course, please let know if you need a pure python approach.
You want to print the variable whose count is not 2
lst = [5, 7 , 5]
for i in lst:
if lst.count(i) != 2:
print(i)
# 7
Or
print(*(i for i in lst if lst.count(i) != 2))
def single(tri):
return tri[2] if tri[0] == tri[1] else tri[:2][tri[0] == tri[2]]
It uses the coercion False = 0 and True = 1.
In contrast to the list expressions, it tests only exactly 2 times for equality (the list expressions test 3 times). So this might be the fastest solution available. Test:
single([5, 5, 7]) ## 7
single([5, 7, 5]) ## 7
single([7, 5, 5]) ## 7

Assign Variable(True/False) to many conditions

I am doing Grok Learning Course, and have come across a problem. Sorry if I have done anything badly; not a professional at coding:
I am trying to make a variable that will be True/False depending on many conditions:
So,
x = True if y > 2 , g < 4 , n != 3
I have tried different ways to do this like:
Assigning variable to each of my conditions:
if y > 2:
ytrue = True
etc..
However, I want to find a better way of doing it than that, which is long and tedious.
Thankyou.
It's as simple as
x = y > 2 and g < 4 and n != 3
which evaluates to True if all three conditions hold and False otherwise.
As you are new to programming, here's how you read it.
First you evaluate the right hand side which is
y > 2 and g < 4 and n != 3
This is evaluated left to right. First it evaluates y > 2 which will either be True or False. If False the whole right hand side is False and False will be assigned to x. Otherwise it keeps on evaluating all of the other sub-expressions on the right hand side until one of them is False or until you've found every one to be True, in which case the whole right hand side is True.
In either case, True or False, your variable x gets the desired value.
x = y > 2 and g < 4 and n != 3
If you have multiple expressions and if you want to do expression on a expression using and's & or's combinations its better to put it on like this
x= ((y > 2 and g < 4) or n != 3)
Comparison operators like (>, <, !=, etc.) all end up being evaluated down to True or False by the python interpreter.
Python also has Boolean the operators and, or, not (Read more in Section 4.2 of the python docs) but you can use these in combination with the comparison operators to chain them. So your assignment becomes:
x = y > 2 and g < 4 and n != 3
You can use ternary conditional operator :
['false','true'][y > 2 and g < 4 and n != 3]
How it works ?
True == 1, False == 0
because booleans are a subclass of int , so [y > 2 and g < 4 and n != 3] produce a integer value but ['false','true'] takes it as index value.
True gives ['false','true'][1]
And False gives ['false','true'][0]
Test case:
y=4
g=1
n=3
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
false
Test case2:
y=4
g=1
n=1
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
true
Now, if you want you can store the result in a variable :
x=['false','true'][y > 2 and g < 4 and n != 3]
which you wanted i think.

How to trace this recursive program

I was wondering if someone would be able to tell me how this program arrives at the correct answer. I have tried to trace it and am not sure where to go because it has an or, so I am confused, how it is supposed to be traced. Thanks for any clarification.
Write a function partition that takes a list of numbers xs, a starting position i, and a desired sum s and returns True or False depending on whether it is possible to find a subsequence of the list elements starting from position i whose sum is exactly s. Note that it is always possible to produce a subsequence of elements whose sum is exactly 0, namely the empty sequence of elements.
def partition(xs,i,s):
print i,s
if i == len(xs):
return s == 0
else:
return partition(xs,i+1,s-xs[i]) or partition(xs,i+1,s)
The rcviz module is a nice tool to help to visualise recursive functions:
The edges are numbered by the order in which they were traversed by the execution. 2. The edges are colored from black to grey to indicate order of traversal : black edges first, grey edges last.
If you follow the calls which are numbered 1-11 you can see exactly what is happening, i starts at 0 then goes to 1, 2 3 and finally 4, the last value on the left is partitition([1,2,3,4],4,-2) so it returns False for s == 0.
Next we go back to where i is 2 then again 3,4 and end up with partitition([1,2,3,4],4,1) so s == 1 again is False.
Next we go from step 6 ending with partitition([1,2,3,4],4,5) where yet again s == 0 is False.
Finally in the right we go from partitition([1,2,3,4],4,7) all the way down to partitition([1,2,3,4],4,0) where s == 0 is True and the function returns True.
If you take the first four calls, you can see how the flow goes and how s is changed.
partitition([1,2,3,4],1,7) # -> xs[i] = 1 s - 1 = 7
partitition([1,2,3,4],2,5) # -> xs[i] = 2 s - 2 = 5
partitition([1,2,3,4],2,5) # -> xs[i] = 3 s - 3 = 2
partitition([1,2,3,4],2,5) # -> xs[i] = 4 s - 4 = -2
s == 0 # -> False
Maybe this version, which is logically equivalent, makes it a bit clearer. The key is that return a or b is equivalent to if a: return a else: return b.
def partition(xs,i,s):
print i,s
if i == len(xs):
# Base case: If the goal is to sum to 0, we succeed.
return s == 0
else:
# First, try including element i in our sum:
first_try = partition(xs,i+1,s-xs[i])
if first_try:
return True
else:
# If first try failed, try not including element i
second_try = partition(xs,i+1,s)
return second_try
This is an explanation of how or works in this context:
return partition(xs,i+1,s-xs[i]) or partition(xs,i+1,s)
will return partition(xs,i+1,s-xs[i]) if this expression evaluates to True. If partition(xs,i+1,s-xs[i]) evaluates to False, partition(xs,i+1,s) will be returned (regardless of whether it evaluates to True or False).
Note you can test this with the following set of simple examples:
In [1]: 1 or 2 # When both are True, the first is returned.
Out[1]: 1
In [2]: 0 or 2 # When the first is False, the second is returned.
Out[2]: 2
In [4]: 0 or False # When both are False, the second is returned.
Out[4]: False
I think it becomes a lot easier to understand if it's written with better names and no indexing:
def can_add_to(numbers, sumwanted):
if not numbers:
return sumwanted == 0
first, *rest = numbers
return can_add_to(rest, sumwanted-first) or can_add_to(rest, sumwanted)
print(can_add_to([1, 4, 9, 25], 13))
This is the same as yours, only more readable. Explanation then:
If there are no numbers, then the answer is "yes" if and only if the wanted sum is zero, and we can say that right away.
Otherwise take the first number (and the rest). You can either use it for the sum or not.
Using it: can_add_to(rest, sumwanted-first) tells you whether the remaining sum (after subtracting first) can be made from the remaining numbers.
Not using it: can_add_to(rest, sumwanted-first) tells you whether the whole sum can be made from the remaining numbers alone.
The overall answer is "yes" if and only if you can make the sum with or without first. That's why you take the two sub-answers and or them together.

Categories

Resources