Absolute value from nested list using recursion - python

I have this nested list:
list1 = [2,-6, [8,-12,-12, [4, [-6], -3]], 7, [3.55, -3.55]].
And I have to use recursion to get absolute values of all elements from the lists so output stays as a list:
[2, 6, [8, 12, 12, [4, [6], 3]], 7, [3.55, 3.55]].
This is the code:
def rec_abs(a):
new_list=[]
for el in a:
if isinstance(el, list):
new_list.append(rek_abs(el))
else:
new_list.append(el)
return new_list
print(rek_abs([2,-6, [8,-12,-12, [4, [-6], -3]], 7, [3.55, -3.55]]))
Can You give me some tips to solve it (I dont expect full solultion, just some tips)?
Thank You a lot!

Everything is perfect, just use abs() to convert it into absolute value
Note : You have typo in code as rec_abs and rek_abs, which I modified it in below code
def rec_abs(a):
new_list=[]
for el in a:
if isinstance(el, list):
new_list.append(rec_abs(el))
else:
new_list.append(abs(el))
return new_list
print(rec_abs([2,-6, [8,-12,-12, [4, [-6], -3]], 7, [3.55, -3.55]]))
[2, 6, [8, 12, 12, [4, [6], 3]], 7, [3.55, 3.55]]

For reference, modifying the list in-place is a simple, more efficient alternative, so you should consider this whenever possible. When iterating, iterate over the indices, and assign the return value to the ith index.
def rec_abs(a):
for i, el in enumerate(a):
a[i] = rec_abs(el) if isinstance(el, list) else abs(a[i])
return a
lst = [2,-6, [8,-12,-12, [4, [-6], -3]], 7, [3.55, -3.55]]
print(rec_abs(lst))
[2, 6, [8, 12, 12, [4, [6], 3]], 7, [3.55, 3.55]]

Related

Unnesting List Function [duplicate]

This question already has answers here:
Flatten an irregular (arbitrarily nested) list of lists
(51 answers)
Closed 1 year ago.
Trying to unnest this list: [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
Into this list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
So far this is my function:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnesting(L):
my_list = []
for element in (L):
if type(element) is list:
my_list.extend(element)
else:
my_list.append(element)
return my_list
except it gives me this output: [1, 2, 3, [4, 5, [6]], 7, 8, 9]
Any solutions or advice on how to unnest this list? Thank you!
You need recursion, otherwise, the function will only work for a nested depth of 2. The important realization is that when your list contains a list again, then you are facing the same problem, i.e. can call the same function again.
The following will work:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnest(lst1, lst2=None):
if lst2 is None:
lst2 = []
for x in lst1:
if not isinstance(x, list):
lst2.append(x)
else:
unnest(x, lst2)
return lst2
flattened = unnest(L)
print(flattened)
I think you're just looking for a short recursive solution here, try this:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnesting(my_list):
if type(my_list) == int:
return [my_list]
return sum((unnesting(elem) for elem in my_list), [])
print(unnesting(L))
Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]
If you have any questions about how this works, leave a comment below and I'll do my best to help you understand.
You can try this. I have just called the function recursively.
my_list = []
def unnesting(L):
for element in L:
if type(element) is list:
unnesting(element)
else:
my_list.append(element)
return my_list
well this is a little different way of doing this. I don't recommend doing it this way. But python allows us to get the result multiple ways.
def unnest(lst):
_ = str(lst)
_ = _.replace('[', '').replace(']', '').replace(',', '').replace(' ', '')
return [int(i) for i in _]
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
unnest(L)

Finding a minimum value in a list of lists and returning that list

This code is supposed to iterate over the list of lists and return the entire list that contains the smallest value. I have already identified that it keeps returning the list at index[0], but I cannot figure out why. Any help, or even hints, would be greatly appreciated.
def list_with_min(list_of_lists):
m = 0
for i in range(len(list_of_lists)-1):
list_i = list_of_lists[m]
min_list = min(list_of_lists[m])
if min_list < list_i[0]:
m = i
answer = list_of_lists[m]
return answer
print(list_with_min([[9, 10, 15], [1, 8, 4], [-3, 7, 8]]))
# [9, 10, 15]--------> should be [-3, 7, 8]
print(list_with_min([[5], [9], [6], [2], [7], [10], [72]]))
# [5]----------------> should be [2]
print(list_with_min([[-2, 6, 9], [-9, 6, 9], [4, 8, 2], [5, -2]]))
# [-2, 6, 9]---------> should be [[-2, 6, 9], [5, -2]] (I assume two lists with the same minimum value should both be returned?)
You can provide a key to the function min, that is a function used for comparison. It turns out that here you want key to be the function min itself.
list_of_lists = [[9, 10, 15], [1, 8, 4], [-3, 7, 8]]
min(list_of_lists, key=min) # [-3, 7, 8]
This does not return multiple minima, but can be improved to do so.
list_of_lists = [[9, 10, 15], [1, -3, 4], [-3, 7, 8]]
min_value = min(map(min, list_of_lists))
[lst for lst in list_of_lists if min(lst) == min_value] # [[1, -3, 4], [-3, 7, 8]]
you can get this in one line with a list comprehension (ive added three though to help you work through the logic), it deals with duplicates differently however:
#for each list return a list with the minimum and the list
mins_and_lists = [[min(_list), _list] for _list in lists]
#find the minimum one
min_and_list = min([[min(_list), _list] for _list in lists])
#parse the result of the minimum one list
minimum, min_list = min([[min(_list), _list] for _list in lists])
if you want to handle duplicate minimums by returning both then:
dup_mins = [_list for _min, _list in mins_and_lists if _min == minimum]
EDIT: A more python way could be this:
def list_with_min(l):
min_vals = [min(x) for x in l]
return l[min_vals.index(min(min_vals))]
A bit bulky but it works...
l=[[9, 10, 15], [1, 8, 4], [-3, 7, 8]]
def list_with_min(l):
m = min(l[0])
for i in l[1:]:
m = min(i) if min(i) < m else m
for i in l:
if m in i:
return i
print(list_with_min(l))
Output:
[-3, 7, 8]
You could also use this:
min([ (min(a),a) for a in list_of_lists ])[1]
Your condition just makes no sense. You're checking
if min_list < list_i[0]:
which means, if the smallest value of list_i is less than the first value of list_i.
I don't think you'd ever want to compare to just list_i[0]. You need to store min_list across loops, and compare to that.

Concatenate pairs of consecutive sublists in a list using Python

How would you combine sublists within a list by pairs?
For example with:
list1 = [[1,2,3],[4,5],[6],[7,8],[9,10]]
the result would be:
[[1,2,3,4,5],[6,7,8],[9,10]]
You could use zip_longest with a fill value (in case your list has an odd number of sublists) to zip an iterator over list1. Running a list comprehension over the zip generator object allows you to concatenate the consecutive pairs of lists:
>>> from itertools import zip_longest # izip_longest in Python 2.x
>>> x = iter(list1)
>>> [a+b for a, b in zip_longest(x, x, fillvalue=[])]
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]]
Try using a list comprehension (but be careful with the indexes!). It works for lists with an even or odd number of sublists:
list1 = [[1, 2, 3], [4, 5], [6], [7, 8], [9, 10]]
n = len(list1)
[list1[i] + (list1[i+1] if i+1 < n else []) for i in xrange(0, n, 2)]
=> [[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]]
list1=[[1,2,3],[4,5],[6],[7,8],[9,10]]
length = len(list1)
new_list = [ list1[i]+list1[i+1] if i+1 < length
else [list1[i]] for i in range(0,length,2) ]
print(new_list)
>>> list1=[[1,2,3],[4,5],[6],[7,8],[9,10]]
>>> list1
[[1, 2, 3], [4, 5], [6], [7, 8], [9, 10]]
Now we can do:
>>> test = [list1[0]+list1[1]]+[list1[2]+list1[3]]+list1[4]
>>> test
[[1, 2, 3, 4, 5], [6, 7, 8], 9, 10]
>>>
I am sure there is a better way, but this is the way I can think of!
list1 = [[1, 2, 3], [4, 5], [6], [7, 8], [9, 10]]
from itertools import islice, chain
print([list(chain.from_iterable(islice(list1, i, i + 2)))
for i in range(0, len(list1), 2)])
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]]
Or without islice:
print([list(chain.from_iterable(list1[i:i+2]))
for i in range(0, len(list1), 2)])
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]]
Use a simple loop:
list1=[[1,2,3],[4,5],[6],[7,8],[9,10]]
newlist = []
for i in range(0, len(list1), 2):
newlist.append(list1[i] + list1[i+1])
if len(list1) % 2 > 0:
newlist.append(list1[-1])
print newlist
Here is (I hope) a correct solution:
def pair_up(ls):
new_list = []
every_other1 = ls[::2]
every_other2 = ls[1::2]
for i in range(len(every_other2)):
new_list.append(every_other1[i]+every_other2[i])
if len(ls) % 2 == 1:
new_list.append(ls[-1])
return new_list
Working on same list with removing n-ths[-1] odd sublists:
for i in range(len(l)/2):#here we go only to last even item
l[i]+=l[i+1]#adding odd sublist to even sublist
l.pop(i+1)#removing even sublist

python get last 5 elements in list of lists

I have a list of lists like this: [[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]].
I want to write a function that will return: [16, 14, 12, 7, 6]: i.e. the last 5 elements in the list of lists.
This is the code I have, but it is not very pythonic at all (master_list contains the list above):
def find_last_five():
last_five = []
limit = 5
for sublist in reversed(master_list):
# have to check that list is not None.
if sublist:
for elem in sublist:
last_five.append(elem)
limit -= 1
if (limit == 0):
return last_five
return last_five
import itertools as it
a = [[1, 2], [4, 5, 6], [], [7, 12, 14, 16]]
reversed(it.islice(it.chain.from_iterable(reversed(a)), 5))
That actually assumes there are no None's in a. If there are just do a = filter(a, None).
Given your example; I will assume your items in your list are either an iterable or None;
>>> import itertools
>>> lst = [[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]]
>>> print list(itertools.chain(*[l for l in lst if l is not None]))[-5:]
[6, 7, 12, 14, 16]
You can use a list comprehension:
>>> tgt=[[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]]
>>> [e for sub in tgt if sub for e in sub][-5:]
[6, 7, 12, 14, 16]
That filters out the None. To filter out other non-list or tuples:
>>> [e for sub in tgt if isinstance(sub, (list, tuple)) for e in sub][-5:]
If you want something that does not have to flatten the entire list of lists first, you can just deal with the structure from the end and move up until you have what you want:
result=[]
current=[]
it=reversed(tgt)
while len(result)<5:
if current:
result.append(current.pop())
continue
else:
try:
current=next(it)
except StopIteration:
break
(Or use John 1024's solution)
Using no external modules:
master = [[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]]
new = []
total = 5
for x in reversed(master):
if x:
new += list(reversed(x))[:total-len(new)]
if total == len(new):
break
print(new)
This produces:
[16, 14, 12, 7, 6]
which is the desired list with the elements in the desired order.
Alternative approach using flatten recipe:
import collections
l = [[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]]
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
for sub in flatten(el):
yield sub
else:
yield el
print([v for v in flatten(l) if v][-5:])
# gives: [6, 7, 12, 14, 16]
How about a different approach?
a = [[1, 2], [4, 5, 6], [], None, [7, 12, 14, 16]]
sum(filter(None, a), [])[-1:-6:-1]
The filter function is necessary only because of the None type in the list. In case it is just a list of lists, this will be lot simpler to write like this:
sum(a, [])[-1:-6:-1]
The principle behind this? We actually use the '+' operator of list to just keep on adding the lists into a single list. Please note that this is not the way to choose(if you choose ;)) for longer lists. For smaller and medium lists, this is fine.
I'd use itertools to do this. Something like
list(itertools.chain.from_iterable(x for x in l if x is not None))[:-5]
where l is your input list.

function that sums up nested list values?

So im attempting to create a recursion function where it takes each item in the list and sums it up altogether, now I know theres a simple built in function sum(a) but I'm trying to work with nested lists such as this below but I keep getting thrown an error.
def sumList():
list2 = [1, [2, 3,[4, 5, 6], 7, [8, [9, 10]], 11]]
newlist = []
lol = 0
for i in range (len(list2)):
if type(list2[i]) == type([]):
print list2[i], "here"
for i in range (len(list2[i])):
lol += (len(list2[i]))
newlist.append(i[:len(i)+1])
if len(list2)==0:
return None
else:
print list2[i]
lol+=list2[i]
print lol
sumList()
Now I know i've got a lot implemented in the program that I imagine isn't needed, but the error I
keep getting is
1
[2, 3, [4, 5, 6], 7, [8, [9, 10]], 11] here
TypeError: object of type 'int' has no len()
In general, you could flatten your list of lists and search for min in the flattened list. There are many recipes for flattening. Below is one that I took from here.
import collections
def flatten(iterable):
for el in iterable:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
yield from flatten(el)
else:
yield el
list2 = [2, 3, [4, 5, 6], 7, [8, [9, 10]], 11]
print(list(flatten(list2)))
# [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
print(sum(flatten(list2)))
# 65
def r_sum(mylist,nsum=0):
for i in mylist:
if isinstance(i,int):
nsum += i
else:
nsum += r_sum(i)
return nsum
# Python 2.7
def recursiveSum(data):
# This naively assumes that if it's not an int, it's a list
# You may want to add more error handling if you expect dirtier data
if isinstance(data, int): return data
mySum = 0
for i in data: mySum += recursiveSum(i)
return mySum
list2 = [1, [2, 3,[4, 5, 6], 7, [8, [9, 10]], 11]]
print recursiveSum(list2) # Should get 66

Categories

Resources