Is this if statement well expressed? - python

I tried to optimize an if statement in one single line and it seems to work properly in my shell but when I test it return nothing. Do you see somethind strange?. The goal of this function is replace the if statement with a single. return statement, and thats what I did.
This is the original function:
def same_length(L1, L2):
'''(list, list) -> bool
Return True if and only if L1 and L2 contain the same number of elements.
'''
if len(L1) == len(L2):
return True
else:
return False
And this is my optimization:
return True if len(L1) == len(L2) else False # Do you see something strange here?
Is this correct?

It is correct, but you do not have to make it so complicated. It is equivalent to:
return len(L1) == len(L2)
There is no need to use an if-statement here: the result of len(L1) == len(L2) is already a boolean. If that boolean is True you return True and the same for False. Simply returning the outcome of the test is equivalent (and more efficient).

Related

Use recursion to determine if a given element is in a list

This should be super simple, I know, but I think there's something inherent about recursion I am not getting. The below code works but is not recursive. I think I just cannot wrap my head around using recursion when it doesn't seem necessary. Anyway. I've been knocking my head against a wall with this for a while, any help appreciated!
def contains_element(my_list, elem):
i=0
while i< len(my_list):
if my_list[i]==elem:
return True
i+=1
return False
print(contains_element([1, 2, 3, 4, 5], 5))
I usually think of recursion the same way I think of induction. To do this, I need to determine two things:
The Base Case
The simplest base case here, would be if my_list == []. If it was the empty list. Clearly in that case, we would return False.
The Iterative Case
Secondly, we want to determine some way to have my_list approach the base case. Here, a simple thing to do would be to pop off the front or back of the list, test that, and then recurse on the remainder of the list.
What does this look like?
def contains_element(my_list, elem):
if my_list == []:
return False
elif my_list[0] == elem:
return True
else:
return contains_element(my_list[1:])
using recursion
check if array is empty or not. if yes then return False
take one element from array, (used pop here, to take last element ) and check whether it is equal to the required element or not.
if equal then return True
using property of or operator, (commutative and associative ie (a or b == b or a ) and (TRUE or True, true or false, false or true, all are true ), just false or false is false ), implement recursion.
where we are checking each element is equal to search value and if yes the return True otherwise call funciton again and check for other elments
it contains(arr, ele) = ((arr[-1] == ele) or (arr[-2] == ele) or (arr[-3] == ele) ... (arr[0] == ele))
def contains(arr, ele):
if not arr:
return False
val = arr.pop()
return val == ele or contains(arr, ele)
arr = list(range(1, 11))
print(contains(arr, 3)) # True
print(contains(arr, 32)) # False

I can't figure out what is wrong with this function?

This is what it should return
Returns True if all items are truthy.
Examples:
>>> all_true([1, True, 'oregonstate'])
True
>>> all_true([0, 1, 2])
False
"""
This is what I have written
def all_true(items):
for i in items:
if i == True:
return True
else:
return False
pass
Not sure why it is not working, can someone help?
Your function just returns the truthiness of the first item in the list, since it always returns on the first iteration.
You want to do something like this:
def all_true(items):
for i in items:
if not i:
return False
return True
Note that this all_true function already exists in Python. It is the the built-in all function.
Two problems. First, you are returning on the first True thing. In fact, you are returning either True or False on the first thing, regardless. Since you return on both the if and its else clauses, the loop will always return on the first iteration. A bit more subtle, but if there aren't any values in the list, it will return None.
Second, if you want "truthy", don't compare specifically to True. foo == True is False. Instead, just let the if do the boolean test
def all_true(items):
for i in items:
if not i:
return False
return True
all and any are builtin functions that do the same thing. It would generally be preferable to use them.
"All items are truthy" is logically equivalent to "no items are falsy."
def all_true(items):
for i in items:
if not i:
return False
return True
Because 0 is falsy. Also there's no need to implement your own function for that, use Python's built–in all() function instead!

Nesting Structure Comparisons

I'm trying to write Nesting Structure Comparison with recursion. Seems pretty basic but doesn't work: when I compare len(original) and len(other) they're different, but it doesn't return False. Why?
def same_structure_as(original,other):
if type(original) != type(other) or len(original) != len(other):
return False
for i in range(len(original)):
if type(original[i]) != type(other[i]):
return False
if type(original[i]) is list and type(other[i]) is list:
same_structure_as(original[i],other[i])
return True
print (same_structure_as([1,[1,1]], [2,[2]]))
As commented, your code did not consider the recursion result. I corrected it and used a combined loop instead of the repeated cumbersome indexing. (I still don't like the multiple return construction). Note that you don't compare simple values in the loop, so an else part for the list type comparison is still needed. Otherwise this works as expected:
def same_structure_as(original, other):
if type(original) != type(other) or len(original) != len(other):
return False
for org_val, other_val in zip(original, other):
if type(org_val) != type(other_val):
return False
if type(org_val) is list and type(other_val) is list:
if not same_structure_as(org_val, other_val):
return False
return True
print (same_structure_as([1,[1,1]], [2,[2]]))
Scratching my original answer, but this is more related to your nested array length.
len([1,[1,1]]) will have a length of 2. It will not count the inner nest items. Therefore, comparing this nested list with other list will pass on your if check.

Overlapping lists function returns False when True in python

I'm a programming semi-noob and am working through Torbjoern Lager's 46 Simple Python Exercises. This is number 10: Define a function overlapping() that takes two lists and returns True if they have at least one member in common, False otherwise. You may use your is_member() function, or the in operator, but for the sake of the exercise, you should (also) write it using two nested for-loops.
def over(list1,list2):
for i in list1:
for j in list2:
return i==j
I thought I had a nice, simple solution, but it can't recognize that the lists overlap, unless the overlapping elements are the first ones.
over(["a","b","c","d"],["e","f","a","h"])
returns False
over(["a","b","c","d"],["a","f","g","h"])
returns True
For some reason, it's not searching through all of the combinations. Any help would be appreciated.
It's not searching through all the combinations because you're returning on the first iteration of the nested loop. You could do this:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
This returns True as soon as any overlap is found. If no overlap is ever found, it'll get to the last line and return False.
The problem is that you return i==j on the first iteration. Your function will justs compare list1[0] and list2[0]. The solution is to add if.
Here is an example:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
You should be testing with an if as suggested in the other answers as you are returning after the very first iteration but using any would be a nicer approach:
def over(list1,list2):
return any(i ==j for i in list1 for j in list2)
Which is equivalent to:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
short circuiting on a match and returning True if there is any match or returning False if there are none.
Or using sets for larger input would be the fastest approach:
def over(list1, list2):
return not set(list1).isdisjoint(list2)
if not set(list1).isdisjoint(list2) is True we have at least one common element.
When you execute the "return" stament de execution stops there, like it happens in Java. It returns true because you have 'a' in the first position in both arrays.
You can try this:
result = False;
for i in list1:
for j in list2:
if i == j:
result=True;
return result
If you want it more efficient:
for i in list1:
for j in list2:
if i == j:
return True;
return False;

Python Recursively check for repeats

I have an assignment I've been stuck on for a couple days now. I have to recursively figure out if a list has repeats but I cannot use any loops or built in functions besides len(). I'm also not allowed to use the 'in' function. Returns True if list L has repeats, False otherwise. This is what I've been able to figure out:
def has_repeats(L):
if len(L) <= 1:
return False
elif L[0] == L[1]:
return True
else: return has_repeats(L[0] + L[2:])
But the problem with that is it's only comparing the first element to the rest, instead of each element to the rest. I can't figure out how to do that without a running counter or something. Any suggestions?
You almost have it. Along with checking the first element with the rest of the list, you also need to check the second the same way:
def has_repeats(L):
if len(L) <= 1:
return False
if L[0] == L[1]:
return True
if has_repeats([L[0]] + L[2:]):
return True
if has_repeats(L[1:]):
return True
return False
You can also compact this into the following representation:
def has_repeats(L):
return len(L)>1 and L[0]==L[1] or has_repeats([L[0]]+L[2:]) or has_repeats(L[1:])
Use a helper function:
def helper(ele, rest):
if not rest:
return False
return ele == rest[0] or helper(ele, l[1:])
def has_repeats(l):
if not l:
return False
return helper(l[0], l[1:]) or has_repeats(l[1:])

Categories