For loop, if statement and Zip python - python-3.x

a= ("Kiran","Narut","Sasue"]
b= ["Kiran","Naruto","Sasuke"]
def quality_check(x,y):
for i,j in zip(x,y):
if i == j:
return "Good to go"
else:
return "wrong names"
quality_check(a, b) # Good to go
It shows unexpected result. The results are shown just for the first element of the lists.

As you are using return It will only check for the first elements.
A return statement is used to end the execution of the function, Replace this with print() will loop over all the elements.

You should use yield instead of return
a= ["Kiran", "Narut","Sasue"]
b= ["Kiran", "Naruto","Sasuke"]
def quality_check(x,y):
for i,j in zip(x,y):
if i == j:
yield "good to go"
else:
yield "wrong"
for element in quality_check(a, b):
print(element)
this will return required results
every time you yield from function it returns a iterable object

Your function quality_check() is returning after the if i == j statement in the first iteration of your for loop. That if statement is comparing "Kiran" == "Kiran" (which is True).
Try checking for only 'Wrong names' in the for loop. Then return 'Good to go' once the loop completes and no Wrong names have been found.
a = ["Kiran", "Narut","Sasue"]
b = ["Kiran", "Naruto","Sasuke"]
c = ["Kiran", "Narut","Sasue"]
def quality_check(x,y):
for i,j in zip(x,y):
if i != j:
return "Wrong names"
return "Good to go"
print(quality_check(a,b))
#> Wrong names
print(quality_check(a,c))
#> Good to go

Related

List comprehention works but normal for loop doesn't - Python

I defined a function to change an element of a list to be number 0, if this element is not a number. It works using list comprehension but it doesn't work when I use a normal for loop.
I'm trying to understand what's is the error in the for loop.
See the code below:
def zerozero(mylist):
mylist = [0 if type(x) == str else x for x in mylist]
return mylist
def zerozero2(mylist):
for x in mylist:
if type(x) == str:
x = 0
else:
x = x
return mylist
Your second function is not quite equivalent. You would need something like this:
def zerozero2(mylist):
new_list = []
for x in mylist:
if type(x) == str:
new_list.append(0)
else:
new_list.append(x)
return new_list
In this manner you can mimic the functionality of the list comprehension, creating a new list and appending items to it as you iterate through.
If you want to modify your list 'in place', you can use this sort of construction:
for idx, x in enumearte(mylist):
if type(x) == str:
mylist[idx] = 0
else:
mylist[idx] = x
However, practically speaking this is unlikely to have much impact on your code efficiency. You can't do this with a list comprehension, and in either case you can just re-assign the new list back to your original variable when you return from the function:
mylist = zerozeroX(mylist)
So what happens is your function is returning the same list as your input.
What you should do is create an empty list first. For example my_list_0 = [].
def zerozero2(mylist):
my_list_0 = []
for x in mylist:
if type(x) == str:
x=0
else:
x=x
my_list_0.append(x)
return my_list_0
The list comprehension essentially returns the new values into your original list, so this is why it is different.

Appending results from a list to a string

Heavy python beginner here. I want to create a simple function for a PIN guessing game that receives two 4-digit lists ( [guess], [answer] ) and returns a string with 4 letters stating how close I am to guessing the correct [answer] sequence (eg. Higher, True, Lower, Higher)
However, I get a new list for each string:
def checkNumbers(guess,right):
for n in range(4):
result = []
if guess[n] == right[n]:
result.append("T") #true
elif guess[n] < right[n]:
result.append("H") #higher
elif guess[n] > right[n]:
result.append("L") #lower
else:
result.append("F") #false
print (result)
return
checkNumbers([1,2,3,5],[2,2,1,6])
The result should look like this:
checkNumbers([1,2,3,4], [2, 2, 1 , 6]) #call function with ([guess], [answer])
'HTLH' #returns a string stating how accurate [guess] is to [answer] list
Result looks like this however:
checkNumbers([1,2,3,5],[2,2,1,6])
['H']
['T']
['L']
['H']
Thanks very much in advance for any help I could get.
you can use string instead of list or "".join()
def checkNumbers(guess, right):
result = ""
for n in range(4):
if guess[n] == right[n]:
result += "T" # true
elif guess[n] < right[n]:
result += "H" # higher
elif guess[n] > right[n]:
result += "L" # lower
else:
result += "F" # false
print(result)
but... maybe you want to use zip function
def checkNumbers(guess, right):
result = ""
for g, r in zip(guess, right):
if g == r:
result += "T" # true
elif g < r:
result += "H" # higher
elif g > r:
result += "L" # lower
else:
result += "F" # false
print(result)
Funny bonus here:
def checkNumbers(guess, right):
print("".join("THL"[(g > r) + (g != r)] for g, r in zip(guess, right)))
I don't get why you need else part...
Initiate the list and print the result outside of the loop:
def checkNumbers(guess, right):
result = []
for n in range(4):
# do loopy stuff
print (result)
return # not strictly necessary
If you do it inside, you are creating a new list on every iteration.

Python: Unexpected result in a recursive function

I've written a recursive function to gauge, e.g. list depth and for some reason it returns unexpected results.
I have two functions:
1. checks if the object is iterable
2. gauges the depth of the object, e.g. list
I think I'm missing something in the second function but I couldn't wrap my head around why exactly variable n when returned from else turns into a funny result.
I set print to see how n gets changed in every stage and it seemed working as expected but when returned from else it turns into a wrong number.
Here are two functions' code:
def isiterable(obj):
'''
takes in an obj and returns 1 if iterable or 0 if not
strings are discarded as iterable
:param obj: any object
:return: int
'''
if isinstance(obj, str):
return 0
else:
try:
iter(obj)
return 1
except TypeError as err:
return 0
my second function is recursive where I'm experiencing problems
def get_depth(a, n=0):
if isiterable(a):
return n + f(a[0], n+1)
else:
return n
I've three examples:
a = [[[1,2], [3,4]], [[5,6],[7,8]]]
b = [[1,2], [2,3]]
c = [2]
I'm expecting get_depth to return 3 for list a, 2 for list b and 1 for list c.
for some reason results for a get doubled and return 6. In b case it is 3 instead of 2.
Many thanks
You don't need to add n when you return from get_depth.
def get_depth(a, n=0):
if isiterable(a):
return get_depth(a[0], n+1)
else:
return n
Because, when a have more depth, you will calculate the get_depth function again witn n+1 which is already count the depth correctly and the extras are not needed.
Btw, you have to think about what if this case?
d = [1, 2, [3, 4]]
I can modify a bit such as:
def get_depth(a, n=0):
if isiterable(a):
temp = []
for i in range(0, len(a)):
temp.append(get_depth(a[i], n+1))
return max(temp)
else:
return n

def function to compare two strings

we need to define a function that compares two strings and if they are different we want to know the index. the problem is that no matter what insert we use we always get -1 even when they are not the same.
def mutation_detector(seq1,seq2):
if DNAval(seq1) and DNAval(seq2) == True:
if len(seq1) == len(seq2):
for i in range(0, len(seq1)) and range(0, len(seq2)):
if seq1[i] != seq2[i]:
return(i)
else:
return(-1)
else:
return('Wrong input')
else:
return('Wrong input')
print(mutation_detector('ATCGGGTA','ATCGGCTA'))
Basically you're using and wrong and have some basic Logic errors I think:
and doesn't say "do A and B" but rather"if A is True and B is True"
My attempt at fixing it is as follows:
if DNAval(seq1) and DNAval(seq2):
if len(seq1) == len(seq2):
for (i, (elem1, elem2)) in enumerate(zip(seq1, seq2)):
if elem1 != elem2:
return i
return -1
Your if-else in the loop always returns in the First loop iteration: it takes the first two chars and compares them; are they equal? No -> return -1
If you follow the logic, it begins comparing strings. If the two letters are the same, it goes for the ELSE (because they are not different) and ends the routine after checking only the first letter.
You only want the routine to return -1 if it makes it all the way through the for loop without returning an index number. So,
Change as below:
def test(seq1, seq2):
if len(seq1) == len(seq2):
for i in range(0, len(seq1)):
if seq1[i] != seq2[i]:
return(i)
return(-1)
else:
return('Wrong input')
print( test('Hello1', 'Hello2'))
print('done')
The problem is, that you are returning -1 on the first time you run through the for loop, because the else-clause is immediately entered.
Use the else clause with the for loop itself instead.
For example:
def compare_strings(seq1, seq2):
if len(seq1) == len(seq2):
for i in range(0, len(seq1)):
if seq1[i] != seq2[i]:
return i
else:
return -1
else:
return 'Wrong input'
(mind you, raising a custom exception might be better than returning "Wrong input" here...)
Here's how I would do it
def mutation_detector(seq1, seq2):
if not DNAval(seq1) or not DNAval(seq2) or len(seq1) != len(seq2):
return "Wrong input" # maybe raise ValueError if DNAval fails instead?
for index, (base1, base2) in enumerate(zip(seq1, seq2)):
if base1 != base2:
return index
return -1
Try this,
It will return index when unable to compare otherwise it will compare two character and to print equal again compare it with length of string.
def mutation_detector(seq1,seq2):
count=0
if len(seq1) == len(seq2):
for i in range(0, len(seq1)) and range(0, len(seq2)):
if seq1[i] != seq2[i]:
return i
else:
count=count+1
if count==len(seq1):
return 'Equal'
print(mutation_detector('ATCGGCTA','ATCGGCTA'))
def comp_string(string1,string2):
if len(string1)!=len(string2):
return "length not equal"
else:
for i in range(len(string1)):
if string1[i] != string2[i]:
return i
return "equal"

why is the print() function prints none in this case

I've been working on a problem I don't understand why the recursive function step returns None?
here is the code :
import sys
def minIndx(list):
x=10
indx=0
for i in range(len(list)):
if (list[i]<x):
x=list[i]
indx=i
return indx
def steps(arr,sum1,sum2,x):
i = minIndx(arr)
del arr[i]
sum1 = sum(arr)
if (sum1 + 9*x >= sum2):
return x
else: steps(arr,sum1,sum2,x+1)
s=input()
digits1=[]
digits2=[]
for i in range(len(s)):
if (i>2):break
digits1.append(int(s[i]))
for i in range(len(s)):
if (i<3):continue
digits2.append(int(s[i]))
sumLeft = sum(digits1)
sumRight = sum(digits2)
print(steps(digits1,sumLeft,sumRight,1))
for the test case : 123456,
the step function prints None as well as the print function
It could be because you're not returning your recursive call. What is your expected output here? When I return the recursive call to steps I get a value of 2 for an input of 123456.

Resources