python nested list comprehensions - python

I am learning python and going through their tutorials. I understand list comprehensions and nested lists comprehensions. With the following code, though, I am trying to understand the order of events.
>>> matrix = [
...[1, 2, 3, 4],
...[5, 6, 7, 8],
...[9, 10, 11, 12],
... ]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4,8,12]]
According to the nested list comprehension, is the first "i" and the second "i" the same variable and do they both increase at the same time? I guess I don't understand how the resulting big list goes from the first sublist [1, 5, 9] to the second sublist [2, 6, 10]

[[row[i] for row in matrix] for i in range(4)]
is equivalent to
my_list = []
for i in range(4):
my_list_2 = []
for row in matrix:
my_list_2.append(row[i])
my_list.append(my_list_2)
is the first "i" and the second "i" the same variable and do they both increase at the same time?
Of course, it is. If it was not the same i, the code would throw an error because one of the two would not be defined.
You may be interested in this question: Understanding nested list comprehension

I made a function in order to do it automatically (sorry for the example, i took it from someone) :
Let's say, you have this example :
# 2-D List
matrix = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flatten_matrix = []
for sublist in matrix:
for val in sublist:
flatten_matrix.append(val)
This is my function :
(first, turn the example into a string that you will send to the function)
x = "for sublist in matrix:for val in sublist:flatten_matrix.append(val)"
then the function :
def ComprenhensionizeList(nested_for_loop_str):
splitted_fors = nested_for_loop_str.split(':')
lowest_val = splitted_fors[1].split(' ')[1]
comprehensionizer = '[ '+ lowest_val+' '+splitted_fors[0]+' '+splitted_fors[1]+' ]'
print(comprehensionizer)
and the output :
[ val for sublist in matrix for val in sublist ]

Related

How to add elements of list of linked list in straight order?

How can I add elements of list of linked list in straight order?
For example, I have list of linked list: [[1, 2, 3], [4, 5, 6], [7, 8]] and list new_list and I wanna add all the elements in order 1->2->3->...->7->8 but not in order 1->4->7->2->5->3->6->8. For second case I have code:
new_list = []
for array in lists:
while array:
new_list.append(array.val)
array = array.next
But how to modify it to get an order as at first case?
Ok so here's what I have simply done:
lists = [[1,2,3],[4,5,6],[7,8]]
new_list = []
for array in lists:
for i in array:
new_list.append(i)
print(new_list)
Output: [1,2,3,4,5,6,7,8]
I don't know why you were using array.next or array.val, however I think you can simply get the list and iterate over it's values and then append it without any problem.
My idea is, I use pop to get the value and then sort the array, you can try my code:
lists = [[1, 2, 3], [4, 5, 6], [7, 8]]
new_list = []
for array in lists:
while array:
new_list.append(array.pop())
new_list.sort()
So you will get the result which you want : [1, 2, 3, 4, 5, 6, 7, 8]

Try To Print Map as str/list/join without succeess

def intersection(list_1, list_2):
return map(lambda list0 : list(dict.fromkeys(list0)), [x for x in list_1 if x in list_2 ])
print(intersection([5, 5, 6, 6, 7, 7], [1, 5, 9, 5, 6]))
In lambda the func that deletes duplicate and in [ ] the list (from list comprehension) the transfered to the func by map.
When I try to turn it into a list / str / join this error accourced.
What can I do and why is this happening ?
I added one example run that suppose to print [5,6] but returns error.
Be noticed that the list itself ([ ]) reutrns alone: [5, 5, 6, 6] because of the duplicates in the original lists.
Also if I change the code from one line to block og code it works:
def intersection(list_1, list_2):
my_list = [x for x in list_1 if x in list_2]
small_func = lambda list0 : list(set(list0))
return small_func(my_list)
returns: [5,6]
Thanks !
I don't think you need map here. Your idea was right to convert to dictionary and than convert back to list but you have to do that only once.
def intersection(list_1, list_2):
return list(dict.fromkeys([x for x in list_1 if x in list_2]))
print (intersection([5, 5, 6, 6, 7, 7], [1, 5, 9, 5, 6]))

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]]

Splicing a list at different intervals based on a value of a list in python

Instead of posting a long winded example, I will post a simplified idea of what I want to achieve.
This is a bit of code that doesn't work, but it is what I want to do. I would like to take the last 4 values of list1 and append them to a new list, then take the last 3 values and append them to the same list and then take the last 2 values and append them to that same list.
Basically print list2 would give [[1,2,3,4],[2,3,4],[3,4]]
Here is the code;
def test():
list1 = range(5)
list2 = []
q=[2,4,6]
j=0
for j in range(len(q)):
list2.append(list1[(q[j]*0.5):])
print list2
Thank you
You can use the following code snippet
list2 = [list1[-i:] for i in range(4,1,-1)]
For example
>>> list1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list2 = [list1[-i:] for i in range(4,1,-1)]
>>> list2
[[6, 7, 8, 9], [7, 8, 9], [8, 9]]
Your code does something different, but after your description, this should do it:
for l in range(len(list1), 0, -1):
list2.append(list1[-l:])

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/

Categories