I have two parameter, for example a,b. I have a situation like if both parameters(a,b) can have values or both may not have values or either of the one them have values.
Example:
1st Condition : a=10, b=20
2nd Condition: a=None, b=20
3rd Condition: a=10 , b=None
4th Condition: a=None, b= None
I have to do some operation if value is present and log it. Currently i am doing like below,
Is there any efficient way to do this?
if not a:
print "Value a not present"
if not b:
print "Value b not present"
# Do operation for A
a = a+1
# Do operation for B
b = b+1
You can collapse everything into two lines:
a = a + 1 if (a is not None) else (a or print('a not present'))
b = b + 1 if (b is not None) else (b or print('b not present'))
If a or b are None, the prints are executed. Here's a demo:
In [692]: a, b = 10, None
In [693]: a = a + 1 if (a is not None) else (a or print('a not present'))
...: b = b + 1 if (b is not None) else (b or print('b not present'))
...:
b not present
In [694]: a, b
Out[694]: (11, None)
At the end of the day, if you were to ask me what to use, I definitely wouldn't recommend the above. Compare this:
def check_and_increment(val):
if val is None:
return print('Not found!')
return val + 1
a = check_and_increment(a)
b = check_and_increment(b)
To my answer above. Which is more readable?
How about just using args instead, if the logic for all the params is going to be same?
def func(*args):
args = [value + 1 if value else value for value in args]
Otherwise, you can reduce the number of conditionals, but you have to use at least one.
Related
I'm trying to build a function that checks which of a,b,c is less then returns the lesser value.
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
elif b < a:
if b < c:
return (b)
elif c < a:
if c < b:
return (c)
else:
return 'none'
So far the code runs fine until it gets to check 'c', then it doesnt return anything, nested if else statements already get really confusing to me.
You shouldn't use if-else as the 3 conditions are not exclusive.
For example, [3, 4, 1] should return in the 3rd condition but is also suitable in the 1st condition, so it returns nothing.
If you don't want to change your code a lot. You can use:
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
if b < a:
if b < c:
return (b)
if c < a:
if c < b:
return (c)
return 'none'
For simple, you can try:
def minimal_three(a,b,c):
return min(a, b, c)
why that code doesn't work:
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
else:
# what if a >= c and a < b ?
return "i returned nothing"
elif b < a:
if b < c:
return (b)
else:
# what if b >= c and a > b ?
return "i returned nothing"
elif c < a:
if c < b:
return (c)
else:
# what if b <= c and a < c ?
return "i returned nothing"
else:
return 'none'
Alternative:
def min_of_two(a, b):
if a > b:
return b
return a
def min_of_three(a, b, c):
min_ab = min_of_two(a, b)
min_abc = min_of_two(min_ab, c)
return min_abc
def min_of_three_v2(a, b, c):
min_ab = a
if a > b:
min_ab = b
min_abc = min_ab
if min_ab > c:
min_abc = c
return min_abc
def min_of_three_v3(a, b, c):
min_abc = a
if min_abc > b:
min_abc = b
if min_abc > c:
min_abc = c
return min_abc
if you really want to use nested if/else (this code is so long):
# if-elif-else is ok.
# nested if is hard to read
# if-elif-elif-elif-elif...-else is hard to read.
# hard to read == easy to have bugs, which is bad.
def min_abc_slower(a, b, c):
if a > b:
# a > b. This means min(a, b) == b
if b > c:
# b > c. This means min(c, min(a, b)) == c
return c
else:
# b > c is False. This means b <= c.
# So, min(c, min(a, b)) == b
return b
else:
# a > b is False. This means a <= b.
# So, min(a, b) = a
if a > c:
# a > c. This means min(c, min(a, b)) == c
return c
else:
# a > c is False. This means a <= c
# So, min(c, min(a, b)) == a
return a
Use the power of if...elif...else over if...if...if or if...else...if...else. The way you have written your code, depreciates the power of elif. The correct way should be as this:
def minimal_three(a,b,c):
if a < b and a < c:
return (a)
elif b < c:
return (b)
else
return (c)
This code will always return the min no matter what numbers you give.
Explaination:
In your code, the line if a < b already tells you the comparison between a and b that which one is greater. So checking for this condition again in the second if if b < a is useless. if a is not lesser than b, then obviously it is either greater than b or equal to b. So now you must just check if b is lesser than c to prove that b is smallest or even a or b both but the returned value is always minimum. I hope you get that.
Also I don't understand whyt do you want to return None. If you provide three numbers to a function to find the minimum number, it should always and always return a number. Tell me a case where you can expect a None.
Easily be done using min inbuilt function:
def min_value(a,b,c):
return (min(a,min(b,c)))
also the number of steps in your code can be reduced with some tweaking.
It works - Finding two greatest in three int:
def Biggest(a, b, c):
if a >= b >= c:
print a, b, 'are the biggest two'
elif b >= c >= a:
print b, c, 'are the biggest two'
else:
print c, a, 'are the biggest two'
Find greatest in three integer:
def Biggest(a, y, z):
Max = a
if y > Max:
Max = y
if z > Max:
Max = z
if y > z:
Max = y
return Max
You could probably get away with using a for loop to minimise lines of code!
It would look something like this:
c = 3
b = 2
a = 1
list = [a,b,c]
def minimal_three(a,b,c):
for y in list:
n = y
for x in list:
if x < n:
print(n)
I've implemented my version of Longest Common Subsequence of Three Sequences and cannot find a mistake. But Coursera grader says that I fail last test case.
It means that the algorithm is almost corrects but outputs a wrong answer in a specific case. But what case is it?
Constraints: length of the list is not less than one and not bigger than 100. Numbers in the lists are integers from -10^9 to 10^9.
import sys
def lcs3(a, b, c):
start_b = 0
start_c = 0
result = []
for i in range(len(a)):
for j in range(start_b, len(b)):
if a[i] == b[j]:
for k in range(start_c, len(c)):
if b[j] == c[k]:
start_b = j+1
start_c = k+1
result.append(a[i])
break
if b[j] == c[k]:
break
return len(result)
def lcs3_reversed(a,b, c):
# check reversed sequence which can be with different order
a_rev = a[::-1]
b_rev = b[::-1]
c_rev = c[::-1]
result = lcs3(a, b, c)
result_reversed = lcs3(a_rev, b_rev, c_rev)
if result == result_reversed:
return result
else:
return result_reversed
if __name__ == '__main__':
input = sys.stdin.read()
data = list(map(int, input.split()))
an = data[0]
data = data[1:]
a = data[:an]
data = data[an:]
bn = data[0]
data = data[1:]
b = data[:bn]
data = data[bn:]
cn = data[0]
data = data[1:]
c = data[:cn]
print(lcs3_reversed(a, b, c))
Update: added the function lcs3_reversed to solve the cases described by you. Anyway cannot pass the test case.
Output should contain the length of common subsequence. For example, for input:
3
1 2 3
3
2 1 3
3
1 3 5
output is 2 because the common part is (1, 3) for these 3 lists.
Runtime for failed case is 0.04 seconds and it looks like that the lists are rather long since most of my own tests worked much faster.
Thanks for your help!
Update2: I've tried another version. First we find the Longest Common Subsequence of 2 lists and then use it again on our result and the 3-rd list.
def lcs2(a, b):
start_b = 0
result = []
for i in range(len(a)):
for j in range(start_b, len(b)):
if a[i] == b[j]:
start_b = j+1
result.append(a[i])
break
return result
def lcs2_reversed(a, b):
# check reversed sequence which can be with different order
a_rev = a[::-1]
b_rev = b[::-1]
result_reversed = lcs2(a_rev, b_rev)[::-1]
return result_reversed
def lcs3_reversed(a, b, c):
lcs2_str = lcs2(a, b)
lcs2_rev = lcs2_reversed(a, b)
lcs3_str_str = lcs2(lcs2_str, c)
lcs3_rev_rev = lcs2_reversed(lcs2_rev, c)
lenghts = [len(lcs3_str_str), len(lcs3_rev_rev)]
return max(lenghts)
if __name__ == '__main__':
an = input()
a = input().split()
bn = input()
b = input().split()
cn = input()
c = input().split()
print(max(lcs3_reversed(a, b, c), lcs3_reversed(a, c, b), lcs3_reversed(b, a, c),
lcs3_reversed(b, c, a), lcs3_reversed(c, a, b), lcs3_reversed(c, b, a)))
Moreover, I tried all the combinations of orders but it did not help... Again I cannot pass this last test case.
Your example breaks with something like:
a = [1,2,7,3,7]
b = [2,1,2,3,7]
c = [1,2,3,1,7]
The sequence should be [1,2,3,7] (if I understand the exercise correctly), but the problem is that the last element of a gets matched to the last elements of b and c, which means that start_b and start_c are set to the last elements and therefore the loops are over.
I was wondering about the most pythonic (and shortest) way to return the variable in an if else that evaluates to FALSE (or TRUE).
def foo(a,b)
if a == 0 or b == 0:
# return b
else:
pass;
a = 0
b = 1
print(foo(a,b))
> 1
Make use of the or operator short-circuiting:
def foo(a, b):
if a == 0 or b == 0:
return a or b
This returns b if a is 0. Note that if a and b are both 0, then 0 is returned.
If you really meant for these values to be booleans, then use the Python bool type values, False and True:
def foo(a, b):
if not (a and b): # equivalent of "not a or not b"
return a or b
foo(False, True) # produces True
foo(True, True) # produces None
Maybe I misunderstood the question, but isn't it the attempt to do this:
a = None
b = 123
c = a or b
print(c)
> 123
It is a pattern for initializing parameters for the functions with defaults if non-mandatory parameter was not set:
def func(a, b=None):
b = b or 'default_value'
print(a, b)
func('abc', 'b defined')
func('cde')
I am given 3 int, a, b, c. I would like to find the sum of all three int provided that they are unique. If a, b, or c has the same values as any of the other values, then they don't count towards the sum.
Example 1:
a = 3, b = 3, c =3
sum = 0
Example 2
a = 1, b = 3, c =3
sum = 1
This is what I have done. Is there a more pythonic way of doing this without so many if else statements?
def lone_sum(a, b, c):
if a != b and b != c and a != c:
return a + b + c
elif a == b == c:
return 0
elif a == b:
return c
elif b == c:
return a
elif a == c:
return b
from collections import Counter
def lone_sum(a, b, c):
d = Counter([a, b, c])
return sum(k for k in d if d[k]==1)
Add any number of numbers:
def lone_sum(*L):
d = Counter(L)
return sum(k for k in d if d[k]==1)
Add numbers repeated exactly c times:
def rep_sum(c, *L):
d = Counter(L)
return sum(k for k in d if d[k]==c)
Add numbers repeated at most c times:
def rep_sum(c, *L):
d = Counter(L)
return sum(k for k in d if d[k]<=c)
... or if you're bored and want to get really creative:
def lone_sum(*L):
nums = set()
all_nums = set()
for num in L:
if num in nums:
nums.remove(num)
elif num not in all_nums:
all_nums.add(num)
nums.add(num)
return sum(nums)
Here is a good beginners way to solve it
def lone_sum(*args):
return sum(x for x in args if args.count(x) == 1)
The issue with this is that args.count is a hidden loop, so the calculation becomes O(n2)
This doesn't matter much if there are only ever 3 arguments - ie n == 3.
A longhand way to write the same thing is
def lone_sum(a, b, c):
args = (a, b, c)
s = 0
for x in args:
if args.count(x) == 1:
s += x
return s
Here I take a list of your numbers, call it x, and then select only those x[i] which are not present in a list which is x without x[i]. That is, it removes all numbers which have a duplicate.
def lone_sum(a, b, c):
x = [a,b,c]
x = [x[i] for i in range(len(x)) if x[i] not in [x[j] for j in range(len(x)) if j!=i]]
return sum(x)
So,
[x[j] for j in range(len(x)) if j!=i]
is basically a list of elements excluding x[i]. It takes all elements apart from ith. If x[i] is in this list, it means it is a duplicate and we need to remove it. That is,
x[i] not in [x[j] for j in range(len(x)) if j!=i]
I think a lot has already been said and done on this topic and there is not much that can be added. But I too have written a program that uses sets to go about this task which is a little different from the top answer. So if you still wish to see all possible programs then here you go. Hope it helps!
def lone_sum(x):
c = set(x)
for b in c:
x.remove(b)
for a in set(x):
if a in c:
c.remove(a)
return(sum(c))
I was doing some practice problems in Coding Bat, and came across this one..
Given 3 int values, a b c, return their sum. However, if one of the values is the same as another of the values, it does not count towards the sum.
lone_sum(1, 2, 3) → 6
lone_sum(3, 2, 3) → 2
lone_sum(3, 3, 3) → 0
My solution was the following.
def lone_sum(a, b, c):
sum = a+b+c
if a == b:
if a == c:
sum -= 3 * a
else:
sum -= 2 * a
elif b == c:
sum -= 2 * b
elif a == c:
sum -= 2 * a
return sum
Is there a more pythonic way of doing this?
Another possibility that works for an arbitrary number of arguments:
from collections import Counter
def lone_sum(*args):
return sum(x for x, c in Counter(args).items() if c == 1)
Note that in Python 2, you should use iteritems to avoid building a temporary list.
How about:
def lone_sum(*args):
return sum(v for v in args if args.count(v) == 1)
A more general solution for any number of arguments is
def lone_sum(*args):
seen = set()
summands = set()
for x in args:
if x not in seen:
summands.add(x)
seen.add(x)
else:
summands.discard(x)
return sum(summands)
Could use a defaultdict to screen out any elements appearing more than once.
from collections import defaultdict
def lone_sum(*args):
d = defaultdict(int)
for x in args:
d[x] += 1
return sum( val for val, apps in d.iteritems() if apps == 1 )
def lone_sum(a, b, c):
z = (a,b,c)
x = []
for item in z:
if z.count(item)==1:
x.append(item)
return sum(x)
Had a very similar approach to what you had:
def lone_sum(a, b, c):
if a != b and b != c and c != a:
return a + b + c
elif a == b == c:
return 0
elif a == b:
return c
elif b == c:
return a
elif c == a:
return b
Since if 2 values are the same the code will automatically return the
remaining value.
I tried this on Codingbat but it doesn`t work, although it does on the code editor.
def lone_sum(a, b, c):
s = set([a,b,c])
return sum(s)