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.
Related
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)
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
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)
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
I'm a beginner in Python programming and I'm having some trouble with some list stuff.
So I want to write a function that returns a boolean value. The function will inform the user whether there is a duplicate consecutive pair of elements in the list he or she entered. By the way, I want to do this using only len(), range(), loops, if-statements, variables and arithmetic (no built in functions).
For example:
contains_consecutive_duplicates([1,3,3]) should return True
contains_consecutive_duplicates([3,2,3]) should return False
My code:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
My logic to this was as follows: Each time the for loop would run, i would refer to some element in the list. If that element was such that the element before it or after it was equal to it, then the for loop would return true. If not, keep searching. If there are none, it would return false.
Now, I actually understand where the error is (I think). The problem is that I don't know how to solve it. I think the for loop is running into a problem at the beginning (when i is reffering to the 0th element). There is no element before the 0th element, hence the error:
"index out of range"
P.S: Is that how you return a boolean value?
Is there a better way to do this?
I would appreciate any help given! Thanks in advance!
#roeland pointed out the problem with assuming iterating the list directly would get you indices (if you want index and value, use enumerate). But in this case you don't actually need the index.
For the simple case (where it's known to be a container you can slice), you can just iterate with zip over offset slices:
def contains_consecutive_duplicates(xs):
return any(x == y for x, y in zip(xs, xs[1:]))
More general solutions can be made with itertools.groupby to handle the case where you can't slice, but this is simple and involves no imports.
Use of any in this case is just a short hand to slurp the generator expression and return True if any values are truthy. The long equivalent form is:
def contains_consecutive_duplicates(xs):
for x1, x2 in zip(xs, xs[1:]):
if x1 == x2:
return True
return False
Since your teacher apparently thinks built-ins are bad, but len and range aren't built-ins (they are), you can do this the dumb way:
def contains_consecutive_duplicates(xs):
for i in range(len(xs) - 1):
if xs[i] == xs[i+1]:
return True
return False
Which does the same work as ziping, just less efficiently (generating index integers and explicitly indexing is surprisingly expensive in Python relative to native iteration).
This should do:
>>> def contains_consecutive_duplicates(xs):
... for i, v in enumerate(xs[:-1]):
... if v == xs[i+1]:
... return True
... else:
... pass
... return False
>>> l1 = [1,3,3]
>>> l2 = [1,3,2]
>>> l3 = []
>>> l4 = [2]
>>> contains_consecutive_duplicates(l1)
True
>>> contains_consecutive_duplicates(l2)
False
>>> contains_consecutive_duplicates(l3)
False
>>> contains_consecutive_duplicates(l4)
False
>>>
By using only range, for and if statements, this can be done with:
def contains_consequtive_duplicates(xs):
for i in range(len(xs)-1):
if xs[i] == xs[i+1]: return True
return False
You access lists with their index and not by their value (which you are by using for i in list). Additionally, if you perform the check xs[i] == xs[i-1] this will not yield the result you want since x[-1] will check the end of the list so [3, 2, 3] will return True.
As a small demonstration:
if contains_consequtive_duplicates([1,3,3]): print "consecutive"
# Prints Consequtive
if contains_consequtive_duplicates([3, 2, 3]): print "consecutive"
# Prints nothing
Try this:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs.indexOf(i)==len(xs):
break
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
What you are doing is trying to do is evaluate xs[i+1], but that does not exist.
This should do the trick:
def contains_consecutive_duplicates(xs):
for i in range(1, len(xs) - 1):
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
return False
It iterates through all values bar the first and last (created by the range function), returning (which ends the loop) if it finds a duplicate.
If it reaches the end and hasn't found a duplicate one must not exist, so it returns False.