Saving result of nested list comprehension - python

I would like to store intermediate results from a nested list comprehension in sublists so that the result looks like this:
example_list = [[[1,2,3], [1,2,3]], [[2,3,4], [2,3,4]]];
sink = [];
for sl in example_list :
temp = [];
for ssl in sl :
temp.append(np.mean(ssl));
sink.append(temp);
expected_result = [[2,2], [3,3]];
How do you perform this using a list comprehension?
I tried something like this, but obviously it doesn't work, I'm blocked on the syntax:
sink = [[np.mean(j)] for i in example_list for j in i];

Not sure what the challenge is. You can create a nested loop within the list. comprehension and store the values.
Here's what I did:
x = [[[i*j*k for i in range (1,4)] for j in range(1,4)] for k in range(1,3)]
print (x)
Output is:
[[[1, 2, 3], [2, 4, 6], [3, 6, 9]], [[2, 4, 6], [4, 8, 12], [6, 12, 18]]]
If you can give me a good use case, it can be implemented.
In the meanwhile, let me see if I can grab some data and show you the implementation.

you can try this;
final_list=[[int(np.mean(ssl)) for ssl in sl] for sl in example_list]
print(final_list)
output:
[[2, 2], [3, 3]]

Related

Sorting elements in a list of lists

Hey I have a list that goes like:
List = [[[1,2],[4,5,3]],[[5,2],[3,4,7]],...]
and I want to sort the elements of each sublist, that the output looks like:
List = [[[2,1],[5,4,3]],[[5,2],[7,4,3]],...]
What I have already tried is creating a loop like this.
for i in List:
for u in [i]:
List[u].sort(reverse = True)
print(List)
but it didnt worked. In other Blogposts I just found ways how to sort the lists, but not the elements in them.
Thanks for your help
You are close, just a few things wrong:
for u in [i]: Do not wrap i in brackets. You are just creating a new list with i as its only element, and looping over that which is not what you want.
Second:
List[u].sort(reverse = True) You do not need to do List[u], rather just u, because inside of this loop, u is equal to the sublist that you want to sort
Also a side note, variables should be lowercase
myList = [[[1,2],[4,5,3]],[[5,2],[3,4,7]]]
for i in myList:
for u in i:
u.sort(reverse=True)
print(myList)
You may use a list comprehension, to easily retrieve the values, iterate over each sublist and sort the subsublist
values = [[[1, 2], [4, 5, 3]], [[5, 2], [3, 4, 7]]]
values = [[sorted(subsub, reverse=True) for subsub in sub] for sub in values]
print(values) # [[[2, 1], [5, 4, 3]], [[5, 2], [7, 4, 3]]]
Or with loops, you can just access the inner lists with the second loop and inline sort them
for sub in values:
for subsub in sub:
subsub.sort(reverse=True)
Note: use meaningful names to your variables
You are close with your approach although in your second loop you’re enclosing i in a list which won’t loop through each sub list and you only need to sort u as you’re not going to slice a list with a list.
for i in List:
for u in i:
u.sort(reverse = True)
print(List)
Result:
[[[2, 1], [5, 4, 3]], [[5, 2], [7, 4, 3]]]
PS If there could be only one layer of nesting then I'd suggest using isinstance to check before looping through and error-ing out due to attempting to sort an int
for i in List:
if isinstance(i[0], list):
for u in i:
u.sort(reverse = True)
else:
i.sort(reverse = True)
Another approach using list comprehension (one liner):
li = [[[1,2],[4,5,3]],[[5,2],[3,4,7]]]
li = [[sorted(i, reverse=True) for i in j] for j in li]
print(li)
Output:
[[[2, 1], [5, 4, 3]], [[5, 2], [7, 4, 3]]]
Is this what you are looking for?
for i in List:
for u in i:
u.sort(reverse = True)
You can use Pandas to sort your data.
import pandas as pd
ist = [[[1,2],[4,5,3]],[[5,2],[3,4,7]]]
df = pd.DataFrame(ist)
I named the columns to read the columns easier.
df.columns = ['a', 'b']
Now we can sort the elements of the lists in each,
df['a'] = df.a.apply(lambda x: sorted(x,reverse=True))
df['b'] = df.b.apply(lambda x: sorted(x,reverse=True))
which yields,
print(df.head())
a b
0 [2, 1] [5, 4, 3]
1 [5, 2] [7, 4, 3]

Recursive method to zip list?

I have got a nested list of list that looks like the following,
list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
However, I would like to find out a method to concatenate the first index of each list with the first index of the other list.
list1 = [[1,4,7,10],[2,5,8,11],[3,6,9,12]]
I have tried doing list comprehension by using the following code
list1 = [[list1[j][i] for j in range(len(list1)) ] for i in range(len(list1[0])) ]
# gives me
# list1 = [[1,4,7,10],[2,5,8,11],[3,6,9,12]]
However, i was hoping alternative methods to achieve the same results, hopefully something that is simpler and more elegant.
Thanks in advance.
zip is a built-in method and does not require outside packages:
>>> list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
>>> print([list(x) for x in zip(*list1)])
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Notice the *list1! This is needed since list1 is a nested list, so the * unpacks that list's elements to the zip method to zip together. Then, since zip returns a list of tuples we simply convert them to lists (as per your request)
A possible recursion solution can utilize a generator:
def r_zip(d):
yield [i[0] for i in d]
if d[0][1:]:
yield from r_zip([i[1:] for i in d])
print(list(r_zip(list1)))
Output:
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
x = min([len(list1[i]) for i in range(len(list1))])
[[i[j] for i in list1] for j in range(x)]
Or try using:
>>> list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
>>> list(map(list, zip(*list1)))
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
>>>

Identify duplicate lists in list of lists?

How can I compare a list of lists with itself in python in order to:
identify identical sublists with the same items (not necessarily in the same
item order)
delete these duplicate sublists
Example:
list = [ [1, 3, 5, 6], [7, 8], [10, 12], [9], [3, 1, 5, 6], [12, 10] ]
clean_list = [ [1, 3, 5, 6], [7, 8], [10, 12], [9] ]
Any help is greatly appreciated.
I can't seem to figure this out.
I would rebuild the "clean_list" in a list comprehension, checking that the sorted version of the sublist isn't already in the previous elements
the_list = [ [1, 3, 5, 6], [7, 8], [10, 12], [9], [3, 1, 5, 6], [12, 10] ]
clean_list = [l for i,l in enumerate(the_list) if all(sorted(l)!=sorted(the_list[j]) for j in range(0,i))]
print(clean_list)
of course, sorting the items for each iteration is time consuming, so you could prepare a sorted list of sublists:
the_sorted_list = [sorted(l) for l in the_list]
and use it:
clean_list = [the_list[i] for i,l in enumerate(the_sorted_list) if all(l!=the_sorted_list[j] for j in range(0,i))]
result (in both cases):
[[1, 3, 5, 6], [7, 8], [10, 12], [9]]
As many suggested, maybe a simple for loop (no list comprehension there) storing the already seen items in a set would be more performant for the lookup of the duplicates. That alternate solution could be necessary if the input list is really big to avoid the O(n) lookup of all.
An example of implementation could be:
test_set = set()
clean_list = []
for l in the_list:
sl = sorted(l)
tsl = tuple(sl)
if not tsl in test_set:
test_set.add(tsl) # note it down to avoid inserting it next time
clean_list.append(sl)
Create a set. Then for each list in the list, sort it, transform into tuple, then insert into set.
setOfLists = set()
for list in listOfLists:
list.sort()
setOfLists.add(tuple(list))
print setOfLists
You can retransform the tuples in the set into lists again.
Simple for loops will work, but if your dataset is small, e.g. 1k or less, you can use this :
b = []
[b.append(i) for i in a if len([j for j in b if set(j) == set(i)])==0 ]
print b
So heres my take on this.
I def a function that sorts each sublist and appends to a temp list. then I check if the sublist in temp_my_list is 'not' in temp_clean_list and if not then append to new list. this should work for any 2 sets of list. I added some extra list to show some kind of result other than an empty string.
my_list = [[1, 3, 5, 6], [7, 8], [10, 12], [9], [3, 1, 5, 6], [12, 10],[16]]
clean_list = [ [1, 3, 5, 6], [7, 8], [10, 12], [9],[18]]
new_list = []
def getNewList():
temp_my_list = []
temp_clean_list = []
for sublist in my_list:
sublist.sort()
temp_my_list.append(msublist)
for sublist in clean_list:
sublist.sort()
temp_clean_list.append(sublist)
for sublist in temp_my_list:
if sublist not in temp_clean_list:
new_list.append(sublist)
getNewList()
print (new_list)
Resulit:
[[16]]

Remove a column from a nested list in Python

I need help figuring how to work around removing a 'column' from a nested list to modify it.
Say I have
L = [[1,2,3,4],
[5,6,7,8],
[9,1,2,3]]
and I want to remove the second column (so values 2,6,1) to get:
L = [[1,3,4],
[5,7,8],
[9,2,3]]
I'm stuck with how to modify the list with just taking out a column. I've done something sort of like this before? Except we were printing it instead, and of course it wouldn't work in this case because I believe the break conflicts with the rest of the values I want in the list.
def L_break(L):
i = 0
while i < len(L):
k = 0
while k < len(L[i]):
print( L[i][k] , end = " ")
if k == 1:
break
k = k + 1
print()
i = i + 1
So, how would you go about modifying this nested list?
Is my mind in the right place comparing it to the code I have posted or does this require something different?
You can simply delete the appropriate element from each row using del:
L = [[1,2,3,4],
[5,6,7,8],
[9,1,2,3]]
for row in L:
del row[1] # 0 for column 1, 1 for column 2, etc.
print L
# outputs [[1, 3, 4], [5, 7, 8], [9, 2, 3]]
If you want to extract that column for later use, while removing it from the original list, use a list comprehension with pop:
>>> L = [[1,2,3,4],
... [5,6,7,8],
... [9,1,2,3]]
>>>
>>> [r.pop(1) for r in L]
[2, 6, 1]
>>> L
[[1, 3, 4], [5, 7, 8], [9, 2, 3]]
Otherwise, just loop over the list and delete the fields you no longer want, as in arshajii's answer
You can use operator.itemgetter, which is created for this very purpose.
from operator import itemgetter
getter = itemgetter(0, 2, 3) # Only indexes which are needed
print(list(map(list, map(getter, L))))
# [[1, 3, 4], [5, 7, 8], [9, 2, 3]]
You can use it in List comprehension like this
print([list(getter(item)) for item in L])
# [[1, 3, 4], [5, 7, 8], [9, 2, 3]]
You can also use nested List Comprehension, in which we skip the elements if the index is 1, like this
print([[item for index, item in enumerate(items) if index != 1] for items in L])
# [[1, 3, 4], [5, 7, 8], [9, 2, 3]]
Note: All these suggested in this answer will not affect the original list. They will generate new lists without the unwanted elements.
Use map-lambda:
print map(lambda x: x[:1]+x[2:], L)
Here is one way, updated to take in kojiro's advice.
>>> L[:] = [i[:1]+i[2:] for i in L]
>>> L
[[1, 3, 4], [5, 7, 8], [9, 2, 3]]
You can generalize this to remove any column:
def remove_column(matrix, column):
return [row[:column] + row[column+1:] for row in matrix]
# Remove 2nd column
copyofL = remove_column(L, 1) # Column is zero-base, so, 1=second column
when you do the del it will delete that index and reset the index, so you have to reduce that index. Here I use the count to reduce and reset the same from the index list we have. Hope this helps. Thanks
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
remove_cols_index = [1,2]
count = 0
for i in remove_cols_index:
i = i-count
count = count+1
del nested_list[i]
print (nested_list)
[j.pop(1) for j in nested_list]
from https://www.geeksforgeeks.org/python-column-deletion-from-list-of-lists/

Python: One-liner to perform an operation upon elements in a 2d array (list of lists)?

I have a list of lists, each containing a different number of strings. I'd like to (efficiently) convert these all to ints, but am feeling kind of dense, since I can't get it to work out for the life of me. I've been trying:
newVals = [int(x) for x in [row for rows in values]]
Where 'values' is the list of lists. It keeps saying that x is a list and can therefore not be the argument if int(). Obviously I'm doing something stupid here, what is it? Is there an accepted idiom for this sort of thing?
This leaves the ints nested
[map(int, x) for x in values]
If you want them flattened, that's not hard either
for Python3 map() returns an iterator. You could use
[list(map(int, x)) for x in values]
but you may prefer to use the nested LC's in that case
[[int(y) for y in x] for x in values]
How about:
>>> a = [['1','2','3'],['4','5','6'],['7','8','9']]
>>> [[int(j) for j in i] for i in a]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Another workaround
a = [[1, 2, 3], [7, 8, 6]]
list(map(lambda i: list(map(lambda j: j - 1, i)), a))
[[0, 1, 2], [6, 7, 5]] #output
You simply use incorrect order and parenthesis - should be:
inputVals = [['1','2','3'], ['3','3','2','2']]
[int(x) for row in inputVals for x in row]
Or if you need list of list at the output then:
map(lambda row: map(int, row), inputVals)
an ugly way is to use evalf:
>>> eval(str(a).replace("'",""))
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
if you don't mind all your numbers in one array you could go:
>>> a = [['1','2','3'],['4','5','6'],['7','8','9']]
>>> map(int,sum(a,[]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In order to map list with any number of dimensions you could use numpy.apply_over_axes
import numpy as np
np.apply_over_axes(lambda x,_:x*2, np.array([[1,2,3],[5,2,1]]),[0])
--------------------
array([[ 2, 4, 6],
[10, 4, 2]])
Unfortunately that doesn't work if you also need to change variable type. Didn't find any library solution for this, so here is the code to do that:
def map_multi_dimensional_list(l, transform):
if type(l) == list and len(l) > 0:
if type(l[0]) != list:
return [transform(v) for v in l]
else:
return [map_multi_dimensional_list(v, transform) for v in l]
else:
return []
map_multi_dimensional_list([[[1,2,3],[5,2,1]],[[10,20,30],[50,20,10]]], lambda x:x*2)
------------------
[[[2, 4, 6], [10, 4, 2]], [[20, 40, 60], [100, 40, 20]]]

Categories