if...else.. compare character list and string by python - python

I am writing an for loop comparing the character in list and string, then return False if the character is not same. But I keep receiving True. Can someone explain what is wrong with my code?
def compare (sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)+1):
if orig[i] == sofar[i]:
return True
else:
return False
return False
here is the result i got:
In [29]: compare (['a','v','c','c','s'], 'abccs')
Out[29]: True
But it suppose to be False

You could just join the characters back into a string
def compare (sofar, orig):
return ''.join(sofar) == orig
Otherwise, if you wanted a loop, you need to compare all characters before you return True. You can return False when the first does not match
Here's another one liner using all() over a loop of zipped characters.
You will need the length check before this statement
return all(x == y for x, y in zip(sofar, orig))
Or going back to the original code, invert your logic
def compare (sofar, orig):
if len(sofar) != len(orig):
return False
for i in range(len(orig)):
if orig[i] != sofar[i]:
return False
return True

If your function reaches a return statement, that's it. Your function has returned a value and it will not continue running.
You can use a generator to implement your logic. The below solution allows you to iterate lazily; retrieve a Boolean list with a letterwise comparison via list; or check if all letters align via all.
def compare(sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)):
if orig[i] == sofar[i]:
yield True
else:
yield False
res = list(compare(['a','v','c','c','s'], 'abccs'))
# [True, False, True, True, True]
res = all(compare(['a','v','c','c','s'], 'abccs'))
# False
Another way of writing your logic without explicit iteration:
lst = ['a','v','c','c','s']
mystr = 'abccs'
res = ''.join(lst) == mystr

The statement return is exit from your function.
So your prog only compares the first element.
if orig[i] != sofar[i]:
return False
would do it

Related

Error when using a variable in recursion to iterate through a binary tree (Python)

def berry_finder(t):
"""Returns True if t contains a node with the value 'berry' and
False otherwise.
>>> scrat = tree('berry')
>>> berry_finder(scrat)
True
>>> sproul = tree('roots', [tree('branch1', [tree('leaf'), tree('berry')]), tree('branch2')])
>>> berry_finder(sproul)
True
"""
if is_leaf(t):
if label(t)=='berry':
return True
else :
return False
else:
if label(t)=='berry':
return True
else:
branch_list=[]
for branch in branches(t):
branch_list+=[berry_finder(branch)]
if True in branch_list:
return True
else:
return False
The code doesn't work.And the function's purpose is to find if any node's value is 'berry'.
The wrong part of the code is the recursion part(i.e. the code under the second else)
I wonder whethet it is the problem of the usage of branch_list,because the branch_list may change during the recursion?
The problem is that you reset branch_list in each iteration of the loop, so losing the previous boolean results, and ending up with only the last result.
You need to move that out of the loop, like so (but read on to reduce the code further -- step by step):
branch_list=[]
for branch in branches(t):
branch_list+=[berry_finder(branch)]
Not a problem, but it is more natural to use append here:
branch_list=[]
for branch in branches(t):
branch_list.append(berry_finder(branch))
And more pythonic is to build the list in one go through map:
branch_list = list(map(berry_finder, branches(t)))
or comprehension:
branch_list = [berry_finder(branch) for branch in branches(t)]
But you don't actually need to collect the booleans in a list at all. Just use any:
return any(map(berry_finder, branches(t)))
The whole function can be reduced to just this:
def berry_finder(t):
return label(t)=='berry' or any(map(berry_finder, branches(t)))
You alread get answer how to use it with list
... but you don't need list for this because you can return True directly when berry_finder(branch) gives first True, and you can return False when you exit loop.
else:
for branch in branches(t):
if berry_finder(branch): #
return True
# --- after loop ---
return False
BTW:
Instead of
if True in branch_list:
return True
else:
return False
you can use shorter
return (True in branch_list) # you can even skip `()`
because ... in ... gives True or False
Similar
return (label(t) == 'berry') # you can even skip `()`
And you would replace results
if True in branch_list:
return False
else:
return True
you can use shorter
return not (True in branch_list)
or
return (True not in branch_list)
but it is not the same as return (False in branch_list)

Palindrome Function Issue

I was writing a function to see whether a string is a palindrome or not and came across an issue with my code. It seems to provide the right answer to most strings, but not to all!
Here it is:
def isPalindrome(string):
for letter in string:
if letter == string[(len(string)-1-string.index(letter))]:
return True
else:
return False
What is wrong with it? Thanks!
Use string slicing
string[start:stop:step]
string[::-1]
Starts from the end and moves towards the beginning, one step at a time.
In other words, slice the word, beginning at last index and move towards the first index.
See String Slicing
This is the most pythonic way to solve the problem.
def palindrome(word: str) -> bool:
return word == word[::-1]
palindrom('scarf')
>>> False # because scarf != fracs
palindrome('rotator')
>>> True # because rotator == rotator
Regarding your current implementation
Your function stops after the first letter because the return statement immediately stops the function and returns the value.
There are many ways to fix your code
Change return to yield, which will return a generator.
Iterating the generator, with list(), will then show True or False for each letter
The result is a palindrome if all() the items are True
This is not an efficient way to solve this problem.
def isPalindrome(string):
for letter in string:
if letter == string[(len(string)-1-string.index(letter))]:
yield True
else:
yield False
test = list(isPalindrome('rotator'))
print(test)
>>> [True, True, True, True, True, True, True]
print(all(test) == True)
>>> True
test = list(isPalindrome('scarf'))
print(test)
>>> [False, False, True, False, False]
print(all(test) == True)
>>> False
Currently you're returning true in cases where not the whole word matches. Only return False if any of the letters dont match, and return True at the end of the loop.
def isPalindrome(string):
for letter in string:
if not letter == string[(len(string)-1-string.index(letter))]:
return False
return True

I have to create a function that returns True or False if a list is sorted

I have to create a function called isSorted() and test if a list is sorted or not in Python 3.7. Said function has to return either True or False for whatever case may occur.
This is my code
def isSorted(newList):
for x in newList:
if newList[0] <= x:
return True
else:
return False
def main ():
newList = [1, 2, 3]
print(isSorted(newList))
newList = [1]
print(isSorted(newList))
newList = list(range(10))
print(isSorted(newList))
newList[9] = 3
print(isSorted(newList))
if __name__ == '__main__':
main()
I specifically need the newList[9] = 3 line to return False, but it keeps returning True. Can anyone explain why?
Two issues:
(1) You should compare each element with the previous one, not with the first element.
(2) You immediately return True if the first check succeeds in the loop. Your code doesn't even process the 9th element.
A fixed implementation could be:
def isSorted(newList):
for i in range(len(newList) - 1):
if newList[i] > newList[i + 1]:
return False
return True
Your test then should print:
True
True
True
False

How do I get my code to only print one output?

Essentially, I am trying to make a function which reads an array, and a number. If the number is within the array, it should return True, and False otherwise. However, I find that for each element in the array there is a True or False - the code checks everything individually, when I only need one True or False; is the number in the array or not ?
def is_it_there(arr, k):
for x in arr:
if x == k:
print(True)
else:
print(False)
is_it_there([8,5,2,234,426,7,11],11)
Like I said before, only one True was expected, but each item was checked and so it was False, False, False, False, False, False, True
It's just
if k in arr:
print(True)
else:
print(False)
or, simpler
print(k in arr)
The problem rises from the fact because you are checking it constantly while looping through the elements. So the code is going to check through constantly whether or not the element is present or not. So you are going to end up printing a statement everytime. Python gives a neat way to do achieve this
def is_it_there(arr, k):
if k in arr:
print(True)
else:
print(False)
is_it_there([8,5,2,234,426,7,11],11)
You can refactor your code like this:
def is_it_there(arr, k):
for x in arr:
if x == k
return True
return False
print(is_it_there([8,5,2,234,426,7,11],11))
If you find the item anywhere in the list, print True and exit the function immediately.
If you make it all the way to the end of the list without finding it, only then print False.
def is_it_there(arr, k):
for x in arr:
if x == k:
# print True and terminate the function
print(True)
return
# if we made it all the way through the loop, we didn't find it
print(False)
However, the 'in' operator already does what you want:
if value in mylist:
print 'True'
else:
print 'False'
You are printing a result each time you do a test in your loop. Try to record the result of each round of your test in a list, and test if there is any "True" value in your result list.
Code Example:
def is_it_there(arr, k):
result = list()
for x in arr:
if x == k:
result.append(True)
else:
result.append(False)
if True in result:
print(True)
else:
print(False)
is_it_there([8,5,2,234,426,7,11],11)

Check if item in list

I have a function like this:
def checks(a,b):
for item in a:
if b[1] == item[1]:
return True
else:
return False
I want to check if the second value of b is in the second value of item in a such as:
checks(['5v','7y'],'6y')
>>> True
But the code I have right now will return False because I believe it's comparing '6y' with '5v'. How do I solve this?
You’re returning True at the right spot, but if the first item doesn‘t match, the function returns False immediately instead of continuing with the loop. Just move the return False to the end of the function, outside of the loop:
def checks(a,b):
for item in a:
if b[1] == item[1]:
return True
return False
True will be returned if an item is matched and False will be returned if the loop finishes without a match.
Anyways, that explains why your code wasn’t working, but use any as suggested by others to be Pythonic. =)
This can be expressed in a simpler way:
def checks(a, b):
return any(b[1] == item[1] for item in a)
You could use any() here:
def checks(a,b):
return any (b[1] == item[1] for item in a)
>>> checks(['5v','7y'],'6y')
True
>>> checks(['5v','7z'],'6y')
False
Help on any:
>>> print any.__doc__
any(iterable) -> bool
Return True if bool(x) is True for any x in the iterable.
If the iterable is empty, return False.

Categories

Resources