divide list using recursion - python

I am trying to implement this function using recursion, the function takes a function parameter f where when passed a value it will return as true or false. It should check all values in the list and store all true values in a list and false values in another list returning them in a tuple.
def divL(f, l):
if not l:
return ([],[])
else:
a = list()
b = list()
for i in range(len(l)):
if f(l[i]):
a.append(l[i])
else:
b.append(l[i])
return (a, b)

Recursive version.
But I agree with others that it is better to do this without recursion.
def divL(f, l):
if not l:
return ([],[])
else:
a, b = divL(f,l[1:])
if f(l[0]):
a.insert(0, l[0])
else:
b.insert(0, l[0])
return (a, b)
#-- test ---
def f(x): return x > 0
divL(f,[1,-2,3,4,2,-5])
([1, 3, 4, 2], [-2, -5])

To solve this problem recursively, then you can start with:
def div_l(fn, elements):
if not elements:
return ([], [])
else:
trues, falses = div_l(fn, elements[1:])
if fn(elements[0]):
trues.append(elements[0])
else:
falses.append(elements[0])
return (trues, falses)
One thing to note about your code, is that, at the moment, there are no recursive calls. In the code above, our base case is when the list of elements is empty (if not elements). Then, we constantly check the first element of the list to see if it satisfies fn, appending it to trues or falses appropriately. Then we pass all the elements of the list besides the first one (elements[1:]) to the function again and repeat until the list is empty.
Having said that, the problem does not seem to be recursive in nature. Why not just use list comprehensions:
a = [element for element in l if f(element)]
b = [element for element in l if not f(element)]
Also, names like a, b, l and f are not great because they say nothing about what they actually mean.
Regarding the way you have written your code so far, the Pythonic way to iterate through the elements of a list is not the same as languages like C/C++/Java/etc; you should rarely need to get list items using their index. Instead you can re-write your for statement as follows:
for element in l:
if f(element):
a.append(element)
else:
b.append(element)
P.S. I haven't tested the code above yet, but it should be a reasonable starting point.

Recursive function that takes split lists as parameters:
def _R(f, l, ts, fs):
if not l:
return ts, fs
if f(l[0]):
return _R(f, l[1:], ts + l[:1], fs)
return _R(f, l[1:], ts, fs + l[:1])
def R(f, l):
return _R(f, l, [], [])
print R( lambda x: x > 10, range(20) )

Related

Is there anyway to re-write this in a more appealing list comprehension format?

What I have here is hard to read and I was wondering how I could write this in fewer lines of code.
lst = [-3,10.5,100]
def add_index(nums):
lst2=[]
add = 0
for i in nums:
add += 1
lst2.append(i+add)
return lst2
add_index(lst)
For each iteration of your loop, add contains a 1-based index and i contains the corresponding list item. There’s a built-in Python function called enumerate that yields each item from an iterable along with its index as an (index, item) tuple.
Example of its use with your loop:
lst2 = []
for i, x in enumerate(nums, start=1):
lst2.append(x + i)
return lst2
which leads to a list comprehension equivalent:
def add_index(nums):
return [x + i for i, x in enumerate(nums, start=1)]
you can use enumerate with an initial value of 1 to pair the list's numbers with the value to add and map the sum function to perform the addition on each pair:
def add_index(nums): return [*map(sum,enumerate(nums,1))]
Of do the addition in a comprehension if you find it more readable:
def add_index(nums): return [add+num for add,num in enumerate(nums,1)]

Method for indexing into a list by a number of dimensions

I am writing code that uses nested lists. My list structure is essentially 2 elements, but the second element comprises two individual elements and so on and so forth. The size of the list therefore grows as 2^n + 1. Anyway, for each recursion of a function I need to be able to access any given element at some 'depth'. Usually, this would be trivial as given,
list1 = [[0,1], [[1,2], [1,0]]]
the following code:
list1[1][1]
would return:
[1,0]
However, for an n dimensional nested list (I use the word 'dimension' fairly haphazardly given that this is a nested list and not an array) I would surely need to 'exponentiate' my [1] index in order to index into each progressively 'deeper' nested list. Is there a trivial way to do this?
Thanks in advance, your help is greatly appreciated.
Use recursion:
def get(li, k):
return get(li[1], k-1) if k > 0 else li
Or iteration:
def get(li, k):
for _ in range(k):
li = li[1]
return li
I created this, I tried to make it as self explanatory as possible:
my_list = [[8,9], [[0,1], [[1,2], [1,0]]]]
# dim=1 -> [8,9]
# dim=2 -> [0,1]
# dim=3 -> [1,2]
# dim=4 -> [1,0]
def get_value_by_dimension(dim :int, lst: list):
x = dim-1
if x==0:
return (lst[0])
else:
try:
return get_value_by_dimension(x, lst[1])
except:
return "Dim is to high!"
print(get_value_by_dimension(2, my_list))
# [0, 1]
print(get_value_by_dimension(1, my_list))
# [8, 9]
print(get_value_by_dimension(5, my_list))
# Dim is to high!

Pairwise multiplier list arguments Python

I'm trying to write a pairwise multiplier function which takes two arguments, both being lists. pairwise_multiply should return a new list with each of the elements in the two input lists multiplied together in a pairwise fashion. e.g.
result = pairwise_multiply([1, 2], [3, 4])
print(result)
> [3, 8]
This is my current function but I keep getting syntax errors:
def pairwise_multiply([l1], [l2]):
i = 0
while 1 <= len(l1):
lst = int(l1[i] * l2[i])
i = i + 1
return lst
In your code here -
def pairwise_multiply([l1], [l2]):
You don't need square brackets to pass lists as arguments. Replace it with -
def pairwise_multiply(l1, l2):
Another implementation, more pythonic would be to use list comprehension with zip -
[i*j for i, j in zip(l1, l2)]
What zip does is (from official documentation)-
Make an iterator that aggregates elements from each of the iterables.
Returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. The iterator stops when the shortest input iterable is exhausted. With a single iterable argument, it returns an iterator of 1-tuples
There are some syntax and logic errors in this snippet.
def pairwise_multiply([l1], [l2]) As #FHTMitchell pointed out, you should cannot not use [...] when naming the arguments. This should be def pairwise_multiply(l1, l2)
while 1 <= len(l1) you mean i, not 1, right? Otherwise you will have an infinite loop. Also, since Python uses zero-based indexing, <= should become <.
You overwrite lst in every iteration. Your function will only return (if at all, see previous point) the result of the last multiplication.
Taking these into account, your code can be transformed to
def pairwise_multiply(l1, l2):
lst = []
i = 0
while i < len(l1):
lst.append(int(l1[i] * l2[i]))
i = i + 1
return lst
But it has many points of failure (for example, what if l1 and l2 are not the same length?), too long and not pythonic.
We can use zip and list comprehension like #ThatBird suggested in their answer.

Modify a int list in function in python

I want to rotate k element in a list in python. For example, n = 7, k = 3, and the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Here is the statement I wrote. It seems to work in the command line.
nums = nums[k%len(nums):] + nums[:k%len(nums)]
But when I encapsulate it in a function like:
def rotate(nums, k):
nums = nums[k%len(nums):] + nums[:k%len(nums)]
return
I want to modify nums directly, but this function doesn't work.
I know that I can use a for loop like:
for i in range(k):
nums.insert(0,nums.pop())
but I want to know why the previous method doesn't work?
What you want is a slice assignment:
nums[:] = nums[k%len(nums):] + nums[:k%len(nums)]
This mutates the list that was passed in, so the change is visible after the function returns. Assigning just to nums merely makes nums point to a different list inside the function; it doesn't affect the original list.
Are you sure you want to modify nums? You need not create a separate list even if you do not modify nums. One advantage of the following approach is that it will work with any sequence.
from itertools import islice
def rotate(lst, k):
n = len(lst)
start = n - (k % n) #handle all ints
for item in islice(lst, start, None):
yield item
for item in islice(lst, 0, start):
yield item
If you insist on modifying nums as you say, you can still do so. E.g.,
nums = [x + 1 for x in range(7)]
nums[:] = rotate(nums,-10)
The nums that is inside the function is only within that function. So you need to return it from that function. One way is like this (python 2.7 code, add parentheses to print if you use 3.x):
nums = [1, 2, 3, 4, 5, 6, 7]
k = 3
def rotate(nums, k):
return nums[k%len(nums):] + nums[:k%len(nums)]
print 'Original', nums
nums = rotate(nums, k)
print 'Rotated', nums

Calculating subsets of a given list recursively

I want to build a recursive function that finds all the subsets of size 'k' of a given list with length n>=k>=0 and returns a list of those subsets.
example:
if the input list is [1,2,3,4] and k = 2 then the function will return
[[4,3],[2,4],[2,3],[1,4],[1,3],[1,2]]
notice that different arrangments of list is considered to be the same list.
I think that this kind of recursion should work:
return [lst[0]] + choose_sets(lst[1:],k-1) ¬¬and¬¬ choose_sets(lst[1:],k)
where choose_sets(lst,k) is the function.
Meaning:
input : [1,2,3,4] , k=3
calls:
[1] + [2,3,4],k=2 and [2,3,4], k=3
and so on...
can anyone guide me as to how I should call those 2 recursive calls 'at the same time' ?
and what should my 'exiting term' be?
Thanks.
Suppose you have a list of size n and you need all subsets of size k.
This is basically the same as:
For each element of the list,
create a new list without the element,
in the new list, find all the subsets of size k-1 (this is the recursive call),
and add the remove element to all the lists.
Now... this solution will have repetitions, for example, in the example you gave, you'll get both [4, 1] and [1, 4]. But it can be changed a little so that it will not create duplicate results.
edit
to handle duplications
def choose_sets(l, k):
if k == 0:
return [[]]
if len(l) == 0:
return []
l2 = l[1:]
subsets = choose_sets(l2, k-1)
for s in subsets:
s.append(l[0])
return subsets+ choose_sets(l2, k)
b = []
def abc(a,k):
if len(a)==k:
b.append(a)
return b
b.extend([a[:k-1]+[i] for i in a[k-1:]])
return abc(a[1:],k)
print abc([1,2,3,4,5],2)

Categories