How do I append things on list through recursion? - python

I have this code:
def positive(A):
if len(A)==0:
return 0
else:
if A[0]>0:
return A [0]+positive(A[1:])
else:
return positive(A[1:])
Theoretically, when I input a list of numbers, it will return the list of positive numbers. For example, when I pass [2,5,-3,-5,2,-6] it will return [2,5,2]. But in my code, what happens is that the positive values are evaluated so this returns 9. I think my problem is that in A [0]+positive(A[1:]) line but I don't know how to change it. Any help is appreciated.

Your code should return a list for every case,
so for the empty list case do return [] and if not A to test for empty list
use A[:1] to get a list of one element instead of A[0] which is an int ( [A[0]] does same)
simplified a bit the else, you don't need them if the previous branches does return
def positive(A):
if not A:
return []
if A[0] > 0:
return A[:1] + positive(A[1:])
return positive(A[1:])
A nice idea from the comments is to use the boolean condition directly as the index to slice with
if A[0]>0 is True, then int(True) == 1 so your slice A[:1]
if A[0]>0 is False, then int(False) == 0 so your slice A[:0] which is empty
def positive(A):
if not A:
return []
return A[:int(A[0] > 0)] + positive(A[1:])
With inline if
def positive(A):
return A[:int(A[0] > 0)] + positive(A[1:]) if A else []

Related

Recursive function return tuples of even index values?

Is it possible to return tuples of only even indexes through recursion?
This is what I came up with it so far.
def even(tup):
if not tup:
return ()
if tup.index(tup[0])+1 % 2 == 0:
return tuple(tup[0]) + even(tup[1:])
Passed argument gonna be look like this:
('c','b','z','e','m','f','j')
And my desired result would be:
First element in the tuple count as 1 = 'c', so for the even numbers it would return b, e, and f instead.
('b','e','f')
There are some requirements that I cannot mutate or re assigning the parameter at all.
What's the best way to approach this recursion?
I can solve this if it was list of numbers, but having a problem with this one.
I was able to come up with this recursive strategy. A noob strategy, I guess. :P
a = ('c','b','z','e','m','f','j')
def recFunc(a, theIndex):
if theIndex%2 == 1:
if theIndex < len(a):
value = recFunc(a, theIndex+1)
return (a[theIndex], ) + value
else:
return ()
else:
return (recFunc(a, theIndex+1))
print(recFunc(a, 0))
It seems to be self-explanatory. :)
Note: Maximum depth reaches at ~1000 elements.
EDIT: If you cannot add any other parameter and change it, how about such a solution (inspired from your work)?
def recFunc(a):
if len(a) == 0 or len(a) == 1:
return ()
# print(a)
return (a[1],) + recFunc(a[2:])
Don't you want just something like this?
tup = tuple(item for i, item in enumerate(tup) if i % 2 == 1)
Recursive function is unnecessary here. If you want to operate with tuple() items I would recommend you to cast it to list().
Also I'm not sure what you are trying to achieve here:
if tup.index(tup[0])+1 % 2 == 0:
tup[0] returns first element
tup.index(tup[0]) returns index of first element => 0
then 0+1 % 2 == 0 is always False
Edit:
But recursive function that returns tuple of "even" index values could look like this:
def even(tup):
if len(tup) <= 1:
return
elif len(tup) <= 3:
return tup[1]
return (tup[1], *even(tup[2:]))

Reverse sign function returns none [duplicate]

This question already has answers here:
Why is "None" printed after my function's output?
(7 answers)
Closed 4 years ago.
I would like to create a function where one passes a list of numbers and gets back another list where the signs of all numbers are reversed. This is my code:
def reverse_sign_of_nos_in_a_list(list1):
""" This function reverses sign of numbers
in a list and returns a list.
"""
list2 = []
for num in list1 :
if num > 0 :
return list2.append(num * -1)
elif num < 0 :
return list2.append(abs(num))
else :
return list2.append(num)
print (reverse_sign_of_nos_in_a_list([1,2,3,-1,-2,-3,0]))
The above code shows None as the output. What's the issue?
The are a couple of things wrong with your code:
You have a return statement in every branch of your code. That means that you will return from the first iteration of the loop no matter what.
list.append modifies the target instance in place. As is conventional in Python for such methods, it returns None, which, combined with #1 means that you always get a return value of None.
There's also something very strange about your code. You flip the sign of a positive number by multiplying by -1. That makes sense. But then you take the absolute value of a negative number. Why? Flipping the sign is the same as multiplying by -1 for negative numbers too. And even for zero.
In fact, you don't even need to multiply by -1. There's already a "flip the sign" operator: unary -.
You can write your function as a single list comprehension:
def reverse_sign_of_nos_in_a_list(list1):
return [-x for x in list1]
list.append() method will append the new element in-place and then will return None. So your function returns that None. Also it will return immediatelly after first element of the original list is processed.
def reverse_sign_of_nos_in_a_list(list1):
""" This function reverses sign of numbers
in a list and returns a list.
"""
list2 = []
for num in list1:
if num > 0:
list2.append(num * -1)
elif num < 0:
list2.append(abs(num))
else:
list2.append(num)
return list2
print(reverse_sign_of_nos_in_a_list([1,2,3,-1,-2,-3,0]))
Please, note I keep the code as close as possible to the original code. I would implement the function differently.
reverse_sign_of_nos_in_a_list is returning None because list.append() returns None, not appended list.
Following should do the job:
def reverse_sign_of_nos_in_a_list(list1) :
""" This function reverses sign of numbers
in a list and returns a list.
"""
list2 = []
for num in list1 :
if num > 0 :
list2.append(num * -1)
elif num < 0 :
list2.append(abs(num))
else :
list2.append(num)
return list2
You need to append and then return the list.
list2.append(...)
return list2
The reason you are getting None as output is because append is a void-Method that does not return a value. It only alters list2.
If you want every element of your list reversed, you should remove all the return which cause the function to return prematurely.
Code
def reverse_sign_of_nos_in_a_list(list1) :
""" This function reverses sign of numbers
in a list and returns a list.
"""
list2 = []
for num in list1 :
if num > 0 :
list2.append(num * -1)
elif num < 0 :
list2.append(abs(num))
else :
list2.append(num)
return list2
print (reverse_sign_of_nos_in_a_list([1,2,3,-1,-2,-3,0]))
Because list.append(elem) -- adds a single element to the end of the list. Common error: does not return the new list, just modifies the original
You should use similar to:
def reverse_sign_of_nos_in_a_list(list1) :
""" This function reverses sign of numbers
in a list and returns a list.
"""
list2 = []
for num in list1 :
if num > 0 :
list2.append(-num)
elif num < 0 :
list2.append(abs(num))
else:
list2.append(num)
return list2
print(reverse_sign_of_nos_in_a_list([1,2,3,-1,-2,-3,0]))
A different, shorter (and kind of more pythonic) way for the whole thing:
def reverse_sign_of_nos_in_a_list(list1):
return [(-1)*ii for ii in list1]

Summing the elements of a list recursively

def sum(L):
if len(L) == 1:
return L[0]
i = sum (len (L) // 2)
if len(L) > 1:
return i + i
L=[2,4]
print (sum(L))
when i try to run it there is a TypeError: object of type 'int' has no len().
In sum (len (L) // 2), you're passing an integer (the result of len(L) // 2) as the L argument to your sum() function. (Please don't give functions the same name as built-in functions.) The recursively-called sum() then tries to evaluate len(L) == 1 on this integer, but integers don't support len(), and so you get the error message in question. What exactly are you actually trying to do?
I think what you were aiming for was to write a recursive sum function that continuously splits the list into smaller chunks. So basically what you need to do is compute the index of the midpoint, then use list slicing to pass the first sublist and second sublist recursively back into the function, until hitting your base case(s) of 0 or 1 elements remaining.
def add(values):
if len(values) == 0:
return 0
elif len(values) == 1:
return values[0]
mid = len(values)//2
return add(values[:mid]) + add(values[mid:])
>>> add([1,2,3,4,5])
15
Don't name your function sum, it shadows the builtin function
Implement your function so as to clearly define a base case and a recursive case.
For the base case, when the length is 1, return that element. You've got this right.
For the recursive case, split your list into half and recursively compute the sum for each half.
def sum_recursive(L):
if len(L) == 1:
return L[0]
idx = len(L) // 2
return sum_recursive(L[:idx]) + sum_recursive(L[idx:])
sum_recursive must always receive a list and return an integer.
Some dry runs:
In [5]: sum_recursive([1, 2, 4, 8])
Out[5]: 15
In [6]: sum_recursive([2, 4])
Out[6]: 6
Keep in mind that this won't be able to handle empty lists as input. If you want to account for that as well, change your base case to:
def sum_recursive(L):
if len(L) <= 1:
return sum(L)
...
We're making use of the builtin sum function here which handles empty lists gracefully by returning 0. For single-element lists, the first element is returned (this is also why it is important you don't shadow these utility functions).
If you don't want to use sum there, you'll need to split your base case into two parts:
def sum_recursive(L):
if len(L) == 0:
return 0
elif len(L) == 1:
return L[0]
...
In your code
i = sum (len (L) // 2)
line is throwing an error because in recursion after the first call of sum() you are passing an integer not list
def sum(L):
if len(L) == 0:
return 0
elif len(L) == 1:
return L[0]
else:
index = len(L)-1
return L[index] + sum(L[0:index])
L=[2,4]
print (sum(L))

How can I return a single boolean value from a recursive function?

I have this function:
def most(P, S):
def recursion(P,S):
if len(S) == 0:
return []
elif P(S[0]):
return [P(S[0])] + recursion(P, S[1:])
else:
return recursion(P, S[1:])
if len(recursion(P,S)) > len(S)/2:
return True
else:
return False
It takes an input of function, P and list, S. If the result of P(S[i]) is true for most of S, then the function most() should return true. Any idea how I can do this recursively without a function inside of a function? In other words, how can I return a single boolean value from a recursive function that takes a list as its input?
Thanks!
The biggest key to recursion is understanding the "terminal condition." What is the state where the function must stop? In this case, it's the empty list.
def most(pred, lst):
if lst == []:
return # but what do we return?
You will need to keep track of the number of list elements that meet an expectation... so you have to keep track of both the expectation (i.e. how many have to be true in order for "most" to be true), as well as the count so far. Let's add those...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
So, then we need to "deconstruct" the list so that we can recurse over it. Let's add that...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
# Check the 'truth' of the head of the list...
if pred(lst[0]):
count += 1
# ...and pass the tail of the list into the next iteration.
return most(pred, lst[1:], threshold, count)
That should be all that you need. Now, I'll caution you that if your lists are of significant length, Python will blow its stack. This is also significantly slower than a solution using a for loop or reduce, because of all the additional function calls.
If I were implementing most for production code, I would do this:
def most(pred, lst):
return sum(1 for x in lst if pred(x)) > len(lst) // 2

Search function python

Hi Im trying to create a search function in python, that goes through a list and searches for an element in it.
so far ive got
def search_func(list, x)
if list < 0:
return("failure")
else:
x = list[0]
while x > list:
x = list [0] + 1 <---- how would you tell python to go to the next element in the list ?
if (x = TargetValue):
return "success"
else
return "failure"
Well, you current code isn't very Pythonic. And there are several mistakes! you have to use indexes to acces an element in a list, correcting your code it looks like this:
def search_func(lst, x):
if len(lst) <= 0: # this is how you test if the list is empty
return "failure"
i = 0 # we'll use this as index to traverse the list
while i < len(lst): # this is how you test to see if the index is valid
if lst[i] == x: # this is how you check the current element
return "success"
i += 1 # this is how you advance to the next element
else: # this executes only if the loop didn't find the element
return "failure"
... But notice that in Python you rarely use while to traverse a list, a much more natural and simpler approach is to use for, which automatically binds a variable to each element, without having to use indexes:
def search_func(lst, x):
if not lst: # shorter way to test if the list is empty
return "failure"
for e in lst: # look how easy is to traverse the list!
if e == x: # we no longer care about indexes
return "success"
else:
return "failure"
But we can be even more Pythonic! the functionality you want to implement is so common that's already built into lists. Just use in to test if an element is inside a list:
def search_func(lst, x):
if lst and x in lst: # test for emptiness and for membership
return "success"
else:
return "failure"
Are you saying you want to see if an element is in a list? If so, there is no need for a function like that. Just use in:
>>> lst = [1, 2, 3]
>>> 1 in lst
True
>>> 4 in lst
False
>>>
This method is a lot more efficient.
If you have to do it without in, I suppose this will work:
def search_func(lst, x):
return "success" if lst.count(x) else "failure"
you dont need to write a function for searching, just use
x in llist
Update:
def search_func(llist,x):
for i in llist:
if i==x:
return True
return False
You are making your problem more complex, while solving any problem just think before starting to code. You are using while loops and so on which may sometimes becomes an infinite loop. You should use a for loop to solve it. This is better than while loop. So just check which condition helps you. That's it you are almost done.
def search_func(lst,x):
for e in lst: #here e defines elements in the given list
if e==x: #if condition checks whether element is equal to x
return True
else:
return False
def search(query, result_set):
if isinstance(query, str):
query = query.split()
assert isinstance(query, list)
results = []
for i in result_set:
if all(quer.casefold() in str(i).casefold() for quer in query):
results.append(i)
return results
Works best.

Categories

Resources