Recursion on nested list - python

I am trying to use recursion on a nested list. Here I am trying to get the innermost element.
input_list = [1,2,3,4,[5,6,7,[8,9,[10]]]]
list1 = input_list
def sublist1(list, sublist=[]):
if len(list) == 0:
return sublist
else:
sublist.append(list)
sublist1(list[1:], sublist)
print(sublist)
sublist1(list1)
The output I am getting is this:
[[1, 2, 3, 4, [5, 6, 7, [8, 9, [10]]]], [2, 3, 4, [5, 6, 7, [8, 9, [10]]]], [3, 4, [5, 6, 7, [8, 9, [10]]]], [4, [5, 6, 7, [8, 9, [10]]]], [[5, 6, 7, [8, 9, [10]]]]]
I tried changing the index but it's not giving me the expected output [10].
Any help would be appreciated.

You can make a recursive call only if any item in the current given list is a list; otherwise it means the current list is already the innermost list, so you can return the list as is:
def inner_most(lst):
for i in lst:
if isinstance(i, list):
return inner_most(i)
return lst
input_list = [1,2,3,4,[5,6,7,[8,9,[10]]]]
print(inner_most(input_list))
This outputs:
[10]
Demo: https://replit.com/#blhsing/SwelteringFlakyDividend

This will answer your nested travels
input_list = [1,2,3,4,[5,6,7,[8,9,[10]]]]
list1 = input_list
def sublist1(list):
if(len(list) > 1):
for l in list:
#print(l)
# print(type(l))
if type(l) == type([]) :
return sublist1(l)
else:
continue
return list
print(sublist1(list1))

print(list1[-1][-1][-1])
This would get you [10]

Related

List index out of range and giving the output ans still

`
list1 = [0,[1, 2, 3], [7, [5, 6]], [7], [8, 9]]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ans=[]
i = 0
n = len(list1)-1
while(n-2):
print(type(list1))
condition = (type(list1[i]) == int)
if condition == True:
ans.append(list1[i])
else:
for j in range(0, len(list1[i])):
condition1 = (type(list1[i][j]) == list)
if condition1 == True:
for k in range(0, len(list1[i][j])-1):
ans.append(list1[i][j][k])
else:
ans.append(list1[i][j])
i+=1
print(ans)
Can anyone help me`
I was trying to simplify the list and i used list for saving it but WHy Index of range. and Still my ans is getting save and giving the right output.
There are 5 items in list1 (see below):
0
[1, 2, 3]
[7, [5, 6]]
[7]
[8, 9]
Your code is incrementing beyond the index of this list
To flatten the list:
list1 = [0,[1, 2, 3], [7, [5, 6]], [7], [8, 9]]
def flatten_list(my_list):
is_not_Flat = True
my_list = [item for sublist in [item if type(item)==list else [item] for item in my_list] for item in sublist]
while is_not_Flat:
for item in my_list:
if type(item) == list:
my_list = flatten_list(my_list)
is_not_Flat = False
return my_list
print(flatten_list(list1))
Output:
[0, 1, 2, 3, 7, 5, 6, 7, 8, 9]

Finding index in nested list

I am trying to create a function that will take as input a nested list and an item, and return a list of indices.
For example list = [0, 5, [6, 8, [7, 3, 6]], 9, 10] and item = 7 should return [2, 2, 0], since list[2][2][0] = 7
my code should work since I can print the desires output, but when i run it it returns None.
def find_item(list_input, item, current):
if list_input == item:
print(current) ## this does give the desires output, but the function should return not print
return current
else:
if isinstance(list_input, list):
for j in range(len(list_input)):
current.append(j)
find_item(list_input[j], item, current)
del current[-1]
what am I overlooking here?
As #tzaman mentioned, you need to handle the return value of find_item recursive call. If the return value of the recursive call is a list, it will mean that searched item is found and we need to stop the recursion.
The following modification will return the earliest found index of the searched item. If no item is found, it will return None.
def find_item(list_input, item, current):
if list_input == item:
return current
else:
if isinstance(list_input, list):
for j in range(len(list_input)):
current.append(j)
search_result = find_item(list_input[j], item, current)
if isinstance(search_result, list):
return search_result
del current[-1]
list_input = [0, 5, [6, 8, [7, 3, 6]], 9, 10]
item = 7
print(find_item(list_input, item, []))
list_input = [0, 5, [6, 8, [7, 3, 6]], 9, 10]
item = 9
print(find_item(list_input, item, []))
list_input = [0, 5, [6, 8, [7, 3, 6]], [30, 4], 9, 10]
item = 4
print(find_item(list_input, item, []))
list_input = [0, 5, [6, 8, [7, 3, 6]], [30, 4], 9, 10]
item = 400
print(find_item(list_input, item, []))
Output:
[2, 2, 0]
[3]
[3, 1]
None
It always bothers me when someone sticks a for loop in the middle of a recursive function! Here's a different way to go about this problem:
def find_item(list_input, item, index=0):
if list_input:
head, *tail = list_input
if head == item:
return [index]
if isinstance(head, list):
if result := find_item(head, item):
return [index] + result
return find_item(tail, item, index + 1)
return list_input
list_input = [0, 5, [6, 8, [7, 3, 1]], 9, 10]
print(find_item(list_input, 7))
This solution doesn't require an explicit third argument. And returns an empty list upon failure to find the item, rather than None. Note the use of the new walrus operator :=
if result := find_item(head, item):
If that's a problem, instead do:
result = find_item(head, item)
if result:

creating combinations from a list of lists

Im trying to figure out how to take a list of lists of integers and create a new list that contains combinations from the list of lists. I want the combination to start with a value from the first list and then respectively take 1 from each of the subsequent lists, only if the value is greater than the previous list.
l=[[1,2,3],[4,8],[5,10]]
# the answer would look like this
correct=[[1,4,5],[1,4,10],[1,8,10],[2,4,5],[2,4,10],[2,8,10],[3,4,5],[3,4,10],[3,8,10]]
>>> from itertools import product
...
...
... def combos(lst):
... result = []
... for p in product(*lst):
... if all(a < b for a, b in zip(p, p[1:])):
... result.append(list(p))
... return result
...
>>> lst = [[1, 2, 3], [4, 8], [5, 10]]
>>> correct = [[1, 4, 5], [1, 4, 10], [1, 8, 10], [2, 4, 5], [2, 4, 10],
... [2, 8, 10], [3, 4, 5], [3, 4, 10], [3, 8, 10]]
>>> combos(lst) == correct
True
List comprehension is probably a great way to go. It works nicely because of your constraints. You probably want something like:
[[i,j,k] for i in l[0] for j in l[1] if j>i for k in l[2] if k>j]
>>> [[1, 4, 5],
[1, 4, 10],
[1, 8, 10],
[2, 4, 5],
[2, 4, 10],
[2, 8, 10],
[3, 4, 5],
[3, 4, 10],
[3, 8, 10]]
This makes a list of lists of the form [i,j,k] for all the i's in l[0] for all the j's in l[1] if j>i and for all the k's in l[2] if k>j (since we already know that j>i at this point)
However, the code above only works for an input list of list of length 3. Took me a little bit, but this recursive approach should work for a input list of any length
def list_of_lists(in_list):
full_list=[]
def recurse(so_far, l):
if l==len(in_list):
return so_far
next_list = in_list[l]
for i in next_list:
if i>so_far[-1]:
new_list = recurse(so_far.copy()+[i], l+1)
if new_list:
full_list.append(new_list)
for i in in_list[0]:
recurse([i],1)
return full_list
l=[[1,2,3],
[4,8],
[5,10]]
ansList = []
for i in range(len(l[0])):
for j in range(len(l[1])):
for k in range(len(l[2])):
if l[0][i]<l[1][j] and l[1][j]<l[2][k]:
ansList.append([l[0][i],l[1][j],l[2][k]])
print(ansList)

How can i create multidimensional list in Python?

How can i create a multidimensional list while iterating through a 1d list based upon some condition.
I am iterating over a 1d list and whenever i find a '\n' i should append the so created list with a new list, for example,
a = [1,2,3,4,5,'\n',6,7,8,9,0,'\n',3,45,6,7,2]
so I want it to be as,
new_list = [[1,2,3,4],[6,7,8,9,0],[3,45,6,7,2]]
how should i do it? Please help
def storeData(k):
global dataList
dlist = []
for y in k:
if y != '\n':
dlist.append(y)
else:
break
return dlist
This is what i have tried.
example code:
lst = [[]]
for x in a:
if x != '\n':
lst[-1].append(x)
else:
lst.append([])
print(lst)
output:
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 0], [3, 45, 6, 7, 2]]
Using itertools.groupby would do the job (grouping by not being a linefeed):
import itertools
a = [1,2,3,4,5,'\n',6,7,8,9,0,'\n',3,45,6,7,2]
new_list = [list(x) for k,x in itertools.groupby(a,key=lambda x : x!='\n') if k]
print(new_list)
We compare the key truth value to filter out the occurrences of \n
result:
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 0], [3, 45, 6, 7, 2]]
This is how I did it but there must be better solutions.
x = 0
output = [[]]
for item in a:
if item != "\n":
output[x].append(item)
else:
x += 1
output.append([])
print(output)
Here is the basic approach:
EDIT: Good heavens! Silly bug... here's a fix:
>>> sub = []
>>> final = []
>>> for e in a:
... if e == '\n':
... final.append(sub)
... sub = []
... else:
... sub.append(e)
... else:
... final.append(sub)
...
>>> final
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 0], [3, 45, 6, 7, 2]]
>>>
There are other ways, but this is the naive imperative way.

python sum right and left components in list

I have a list:
key: [[1, 3, 4, 5, 3]]
I need to get list like
key: [[6, 5, 8, 7, 6]]
How can I do that with Python?
A simple approach:
>>> my_list = [1, 3, 4, 5, 3]
>>> new_list = []
>>> for i,x in enumerate(my_list):
... if i==0:
... new_list.append(my_list[-1] + my_list[i+1])
... elif i==len(my_list)-1:
... new_list.append(my_list[0] + my_list[i-1])
... else:
... new_list.append(my_list[i-1] + my_list[i+1])
...
>>> new_list
... [6, 5, 8, 7, 6]
you could use list comprehension:
[a[i-1]+(a+a[:1])[i+1] for i in range(len(a))]
this works because:
a[-1] returns the last element of the list
a+a[:1] appends the first element of the list to the end
A functional approach:
from operator import add
list(map(add, key[1:]+key[:1], key[-1:] + key[:-1]))
# [6, 5, 8, 7, 6]

Categories