Python: Flattening an index by only one level [duplicate] - python

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 2 years ago.
I'm aware of how completely flattening a list of sublists is done, however, I am unsure of how to do so by only one level.
For example, a sublist like [[[1, 2], 3], [[4, 5], 6], [[7, 8], 9]] would get flattened into [1, 2, 3, 4, 5, 6, 7, 8, 9].
However, I'm struggling to figure out a way for the result to be [[1, 2, 3], [4, 5, 6], [7, 8, 9]], without ending up flattening the entire list.
Any help will be appreciated!

input_array = [([1, 2], 3), [[4, 5], 6], [[7, 8, (9, [10])], 11]]
result_array = []
def flat_element(el):
global result_array
_class = ''
try:
_class = str(type(el)).split("'")[1]
except:
pass
if _class in ('list', 'tuple'):
for elem in el:
flat_element(elem)
else:
result_array.append(el)
flat_element(input_array)
print(result_array)
main_array = []
for sub_array in input_array:
result_array = []
flat_element(sub_array)
main_array.append(result_array)
print(main_array)
example_array = [[[1, 2], 3], [[4, 5], 6], [[7, 8], 9]]
main_array = []
for sub_array in example_array:
result_array = []
flat_element(sub_array)
main_array.append(result_array)
print(main_array)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[[1, 2, 3], [4, 5, 6], [7, 8, 9, 10, 11]]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Working with arrays and tuples

Related

Remove 2 duplicated swap sublists in list

I have a two-dimensional list like this:
[[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
I want to remove all the sublists that are duplicates but in reverse order (ie: [1, 6] and [6, 1], [3, 7] and [7, 3]).
The result should be:
[[1, 6], [2, 5], [3, 7], [8, 9]]
You can use set and frozenset:
lst = [[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
output = set(map(frozenset, lst))
print(output)
# {frozenset({1, 6}), frozenset({2, 5}), frozenset({3, 7}), frozenset({8, 9})}
If you want to have a list of lists, then you can append the following:
output = list(map(list, output))
print(output)
# [[1, 6], [2, 5], [3, 7], [8, 9]]
You can do this easily by checking if the sorted list is already had already been added. Like this:
data = [[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
new_data = []
for lst in data:
if sorted(lst) not in new_data:
new_data.append(lst)
print(new_data) # => [[1, 6], [2, 5], [3, 7], [8, 9]]
This works because [1, 6] and [6, 1] return the same sorted list.

how to delete the short lists from a long nested list even the items are not continuous using Python?

For example:
t=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
I want to delete the short lists if the items are included in a long one, even the items are not continuous. So, I expect the result to be:
[[1, 2, 3, 4, 5, 6],[6,7]]
I might figure out this by myself, but my way is not smart enough. Could anyone help me here?
Since all the elements in a list is unique, AND I like using sets
here's my code. Haven't checked it's efficiency but it looks cleaner :D
t = [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
t = [set(l) for l in t]
t = [list(x) for x in t if not any([x.issubset(y) for y in t if x != y])]
Sort from small to large, make them sets then pop them off the list to reduce the list size for every computation.
t=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
t = sorted(t, key=lambda x: len(x))
t = [set(x) for x in t]
for i in range(len(t)):
a = t.pop(0)
if not any([a.issubset(x) for x in t]):
print(a)
My approach is very simple
I check the last element is already present in our longer list. If we present then we don't need to add to the longer list if it is not the case then we will add to the longerlists
sorted_lists=[[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [2, 3, 4, 5, 6], [3, 5], [4, 5, 6],[4,5,6],[6,7], [6], [1]]
sorted_big_lists =[]
for sorted_list in sorted_lists:
for test_list in sorted_big_lists:
if sorted_list[-1] in test_list:
break
else:
sorted_big_lists.append(sorted_list)
print(sorted_big_lists)

Combination of few list with keeping order

I have a few lists that I want to make combinations the output should have the first item from list1 second from list2 and last from list3.
I tried with for and append but it did not work can itertools be used?
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [7, 8 ,9]
Output should be
[[1,4,7],[2,4,7]...[3,6,9]]
You can also try considering simple list comprehension. What makes your question unique is the order of elements. The key point here is to have list1 as the inner most loop just to have the output in the order you want.
result = [[i, j, k] for k in list3 for j in list2 for i in list1]
Output
[[1, 4, 7],
[2, 4, 7],
[3, 4, 7],
[1, 5, 7],
[2, 5, 7],
[3, 5, 7],
[1, 6, 7],
[2, 6, 7],
[3, 6, 7],
[1, 4, 8],
[2, 4, 8],
[3, 4, 8],
[1, 5, 8],
[2, 5, 8],
[3, 5, 8],
[1, 6, 8],
[2, 6, 8],
[3, 6, 8],
[1, 4, 9],
[2, 4, 9],
[3, 4, 9],
[1, 5, 9],
[2, 5, 9],
[3, 5, 9],
[1, 6, 9],
[2, 6, 9],
[3, 6, 9]]
You can use numpy
print([list(x) for x in numpy.array(numpy.meshgrid(list1,list2,list3)).T.reshape(-1,len(a))])
Outputs:
[[1, 4, 7], [1, 5, 7], [1, 6, 7], [2, 4, 7], [2, 5, 7], [2, 6, 7], [3, 4, 7], [3, 5, 7], [3, 6, 7], [1, 4, 8], [1, 5, 8], [1, 6, 8], [2, 4, 8], [2, 5, 8], [2, 6, 8], [3, 4, 8], [3, 5, 8], [3, 6, 8], [1, 4, 9], [1, 5, 9], [1, 6, 9], [2, 4, 9], [2, 5, 9], [2, 6, 9], [3, 4, 9], [3, 5, 9], [3, 6, 9]]

Why is my original 2D array being modified in the following code

Im trying to solve a coding problem where i have to generate some matrices, im new to python and i cant figure out why my matrix keeps getting changed to the latest matrix being generated. Here's the code i have so far:
def mirrorHorizontal(m):
l = list(m)
matrix_len = len(l)
for x in range(0,matrix_len):
temp = l[x][matrix_len-1]
l[x][matrix_len-1] = l[x][0]
l[x][0] = temp
return l
def mirrorVertical(m):
l = list(m)
matrix_len = len(l)
for x in range(0,matrix_len):
temp = l[0][x]
l[0][x] = l[matrix_len-1][x]
l[matrix_len-1][x] = temp
return l
def rotateMatrix(m):
l = list(m)
matrix_len = len(l)
rotated_matrix = []
for x in range(0,matrix_len):
rotated_row = []
for y in range(0, matrix_len):
rotated_row.append([(matrix_len-1) -y][y])
rotated_matrix.append(rotated_row)
return rotated_matrix
# Complete the formingMagicSquare function below.
def formingMagicSquare(s):
all_matrices = []
base_matrix = [[8,3,4],[1,5,9],[6,7,2]]
all_matrices.append(base_matrix)
print("all matrices after first append",all_matrices)
base_h_mirror = list(mirrorHorizontal(base_matrix))
print("horizontal_mirror",base_h_mirror)
all_matrices.append(base_h_mirror)
print("all matrices after first h mirror append",all_matrices)
base_v_mirror = list(mirrorVertical(base_matrix))
print("vertical_mirror",base_v_mirror)
all_matrices.append(base_v_mirror)
print("all matrices after first v mirror append",all_matrices)
#Same as vertical mirror of horizontal mirror
base_v_h_mirror = list(mirrorHorizontal(base_v_mirror))
all_matrices.append(base_h_mirror)
print("h_mirror added",all_matrices)
all_matrices.append(base_v_mirror)
print("h_mirror added",all_matrices)
all_matrices.append(base_v_h_mirror)
print("base_v_h_mirror added",all_matrices)
print("mirrored matrices= ",all_matrices)
matrix_len = len(all_matrices)
for x in range(0,matrix_len):
all_matrices.append(rotateMatrix(all_matrices[x]))
print(all_matrices)
formingMagicSquare()
The output , if you run it is something like:
all matrices after first append [[[8, 3, 4], [1, 5, 9], [6, 7, 2]]]
horizontal_mirror [[4, 3, 8], [9, 5, 1], [2, 7, 6]]
all matrices after first h mirror append
[
[[4, 3, 8], [9, 5, 1], [2, 7, 6]],
[[4, 3, 8], [9, 5, 1], [2, 7, 6]]
]
vertical_mirror [[2, 7, 6], [9, 5, 1], [4, 3, 8]]
all matrices after first v mirror append
[[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]]]
h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
base_v_h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
mirrored matrices= [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
Why is my matrix being populated with the same matrix again and again? I converted the list in the functions i used by slicing it [:]
This is also related to mutable and immutable types. You are dealing with lists of lists, which are lists of mutables. So the inner lists are passed by reference, even if you use [:] which makes a shallow copy: a copy of the container, but holding references to the inner object if they are mutables.
That's why, when you change the inner lists, you are changing the same inner lists each time. They are all references to the same lists.
Have a look at the copy docs to more details about shallow copies and deep copies. This will also give you a solution: use a deep copy.
In each function, replace:
l = list(m)
with:
l = copy.deepcopy(m)

permutation of elements inside the list of list

I have a nested list as follows:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I need to permute only the elements inside each list.
do you have any idea how can I do this?
You can do something like this:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for x in A:
random.shuffle(x)
To shuffle each sublist in a list comprehension, you cannot use random.shuffle because it works in place. You can use random.sample with the sample length = the length of the list:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_a = [random.sample(l,len(l)) for l in A]
print(new_a)
an output:
[[2, 1, 3], [5, 4, 6], [7, 9, 8]]
That solution is the best one if you don't want to modify your original list. Else, using shuffle in a loop as someone else answered works fine as well.
Use permutations from itertools:
from itertools import permutations
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
out = []
for i in A:
for j in permutations(i):
out.append(list(j))
print out
OUTPUT:
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1],
[4, 5, 6], [4, 6, 5], [5, 4, 6], [5, 6, 4], [6, 4, 5], [6, 5, 4],
[7, 8, 9], [7, 9, 8], [8, 7, 9], [8, 9, 7], [9, 7, 8], [9, 8, 7]]

Categories

Resources