creating a nested list from flat list with defined dimension - python

i have a flat list that i want to transform into nested list based on the defined dimension, the length of the flat list can be arbitrary, but the dimension should satisfy the length of the list, for example
[0,1,2,3,4,5,6,7]
will produce a nested list
m = 2
n = 4
[[0,1][2,3][4,5][6,7]]
or
m = 4
n = 2
[[0,1,2,3][4,5,6,7]]
i am thinking of using list comprehension to generate the nested list, but other option can also appending element from the flat list
a = [[i] * m for i in range(n)]

You can try this:
m = 2
n = 4
nums = [i*m for i in range(1,n+1)]
[list(range(x,y)) for x, y in zip([0] + nums, nums)]
OR
nums = [i*m for i in range(n)]
[list(range(z,z+m)) for z in (nums)]
Output:
[[0, 1], [2, 3], [4, 5], [6, 7]]
For
m = 4
n = 2
Output:
[[0, 1, 2, 3], [4, 5, 6, 7]]

Here's one option using list comprehensions:
col = list(range(10))
[
col[col.index(val):col.index(val) + m]
for val in col[::len(col)//n]
]

Related

Fill Matrix Rows in Python

Let's say we have a nested list in Python. AKA a matrix, and we have a list consisting of elements, lets say li = [1, 2, 3, 4, 5, 6]. I want to insert two elements in matrix rows, resulting matrix = [ [1,2] [3,4], [5,6] ]. How can this be done ? Thanks!
b = [[]]
c = [1, 2, 3, 4, 5, 6]
for i in range(len(c)):
for j in range(2):
b[i].append(c[i])
print(b)
How can this be done ?
split the list with slices
a[0:2],a[2:4],a[4:6]
append each of those to an empty list
or construct a list with those slices as the items
You can do it just like this:
c = [1, 2, 3, 4, 5, 6]
b = []
fixed_c = []
for i in range(len(c) + 1):
if len(b) < 2 :
b.append(c[i])
elif len(b) == 2 and i != len(c):
fixed_c.append(b)
b = []
b.append(c[i])
else:
fixed_c.append(b)
print(fixed_c)

Python Sum with 3 nested list and empty list Explanation

l = [ [[1,2,3], [2,3,4]] ]
sum(l,[])
Output ist
[[1, 2, 3], [2, 3, 4]]
I don't know why it works like this.
I tired the two below
[].__add__(l) # First Try
[] + l # Secodn Try
In both cases, the output was as follows.
[[[1, 2, 3], [2, 3, 4]]]
I don't know what the difference is from the sum operation.
My python version is 3.8.12
sum takes a list of values and adds all of them together. E.g. for a list of numbers:
l = [1, 2, 3]
sum(l)
does:
0 + 1 + 2 + 3
As you see, the outer list does not appear in the operations nor result.
Now, with your example:
l = [ [[1,2,3], [2,3,4]] ]
sum(l, [])
that's concatenating all the values in l:
[] + [[1,2,3], [2,3,4]]
Which is not the same as:
[] + [ [[1,2,3], [2,3,4]] ]
If I understand correctly you want to add 1 to every item in the list, if so this code should work.
x = [[[1,2,3], [2,3,4]]]
for i in range(len(x[0])):
for j in range(len(x[0][i])):
x[0][i][j] += 1
print(x)

Multiply a list by the elements of other list

I have this list of list, with a series of values:
factors = [1,2,3]
values = [[1,2,3],[3,1,4],[5,5,2]]
I want to multiply each list1 in values, but the corresponding element of list1. I am trying with this:
factors = [1,2,3]
values = [[1,2,3],[3,1,4],[5,5,2]]
multiply = []
for i in factors:
multiply = [values[i]*i]
But it does not work. The expected value would be:
[[1, 2, 3], [6, 2, 8], [15, 15, 6]]
Try this:
factors = [1, 2, 3]
values = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
multiply = []
for idx, lst in enumerate(values):
multiply.append([factors[idx] * x for x in lst])
print(multiply)
For a list comprehension version of the above code, see #Hommes answer
Update: Given more general setup of the problem I changed the comprehension
Solution with list comprehension:
factors = [1, 2, 3]
values = [[1, 2, 3], [3, 1, 4], [5, 5, 2]]
multiply = [[factors[idx] * elem for elem in lst] for idx, lst in enumerate(values)]
Out[39]: [[1, 2, 3], [6, 2, 8], [15, 15, 6]]
There is a few problems with the code as it is:
Python uses zero-indexing
The first element of a list in Python has the index 0. In your for loop:
for i in factor:
multiply = [values[i]*i]
The last iteration will try to access values[3]. But values has only 3 elements, so the last element is values[2], not values[3].
Multiplication * of a list and an integer doesn't actually multiply
Multiplying a list by an Int, say n gives you a new list that concatenates the original n times. For example:
>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
The most straightforward way of actually broadcasting the multiplication over the list is to use a 'list comprehension'. For example:
>>> [3*x for x in [1,2,3]]
[3, 6, 9]
Applying this into your example would look something like:
for i in factors:
multiply = [i*x for x in values[i-1]]
You are only keeping the last calculation in multiply
Each go around your for loop you assign a new value to multiply, overwriting whatever was there previously. If you want to collect all your results, then you should append to the multiply list.
multiply.append([i*x for x in values[i-1]])
All together, your example is fixed as:
factors = [1,2,3]
values = [[1,2,3],[3,1,4],[5,5,2]]
multiply = []
for i in factors:
multiply.append([i*x for x in values[i-1]])
Improvements
However, there are still ways to improve the code in terms of concision and readability.
The root of the problem is to multiply a list's elements by a number. * can't do it, but you can write your own function which can:
def multiply_list(X, n):
return [n*x for x in X]
Then you can use this function, and a list comprehension, to remove the for loop:
multiply = [multiply_list(x, i) for (x, i) in zip(values, factors)]
Or, if you think it is readable, then you can just use the nested list comprehension, which is much more concise:
multiply = [[factor * x for x in value] for (value, factor) in zip(values, factors)]
You can use list comprehension for a one liner. Try this
multiply = [[x * y for y in list1] for x in list1]

Fill lists in list with zeros if their length less than

I have a list of lists with different sizes but I want to make them all the same length. For example, make them with length of 5 by padding with zeros if length less than 5 or cut the list if length is more than 5. For example, I have a list:
foo = [
[1, 2, 3],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 6, 7]]
result = [
[1, 2, 3, 0, 0],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
Do you have an idea of optimal and fast solution, if the list of lists is large?
List comprehension
Make a fill list and use slicing to get the appropriate lengths.
n = 5
fill = [0] * n
result = [sublist[:n] + fill[len(sublist):] for sublist in foo]
result = []
for sublist in foo:
size = len(sublist)
result.append(sublist[:5] + [0]*(5 - size))
To perform this optimization, i sliced additional elements beyond n = 5, and replaced with 0 those not reaching n = 5 by checking how many elements they miss.
def listOptimization(foo, n):
# slicing foo to have n elements on all child elements of foo
for i in range(len(foo)):
foo[i] = foo[i][:n]
# optimizing
for i in range(len(foo)):
# check if foo child element is less than n
# if true, append to the list with 0 depending on how many
# elements to reach n
if len(foo[i])<n:
temp = n-len(foo[i])
for x in range(temp):
foo[i].append(0)
return foo
result = [[bar[i] if i<len(bar)else 0 for i in range(5)] for bar in foo]
there are 5 elements in a row, so for i in range(5), the exceed 5 will be discard. then assign value directly,if the length of each row is less than i, assign 0
Actually, I found a pretty fast solution for me. If you have an idea how to solve it without a for loop please post.
for row in foo:
while len(row) < 5:
row.append(0)
else:
row[:5]

nested lists in python

I am trying to split the following list:
A_list = [[[1,2,3,4],[5,6]], ==>[0]
[[3,4,5],[2,3,5]], ==>[1]
[[5,8,9],[10,11]], ==>[2]
[[22,20],[5,7,8]]] ==>[3]
to:
x_list = [[1,2,3,4],[5,6],
[5,8,9],[10,11]]
y_list = [[3,4,5],[2,3,5] ,
[22,20],[5,7,8]]
x_list has row [0] , row [2] and row [4] ....
y_list has row [1] , row [3] and row [5] ...
where each row has 2 lists
is there any way to do that?
thank you for help or hints
I should mention that 'A_list' in this question has been modified. It was as below:
A_list = [[1,2,3,4],[5,6], ==>[0]
[3,4,5],[2,3,5], ==>[1]
[5,8,9],[10,11], ==>[2]
[22,20],[5,7,8]] ==>[3]
most of the posted answers were to the question before editing. Thanks for all the helpful answers.
(This first part of this answer was written before the question was edited, changing the layout of A_list.) Your list does not have "rows". Instead, you want to assign the 1st and 2nd element to x_list, the 3rd and 4th to y_list, 5th and 6th to x_list again, and so on.
For this, you can enumerate the elements in your list and assign them to x_list and y_list based on their index modulo 4.
>>> x_list = [a for i, a in enumerate(A_list) if i % 4 < 2]
>>> x_list
[[1, 2, 3, 4], [5, 6], [5, 8, 9], [10, 11]]
>>> y_list = [a for i, a in enumerate(A_list) if i % 4 >= 2]
>>> y_list
[[3, 4, 5], [2, 3, 5], [22, 20], [5, 7, 8]]
Or, you could first create those rows by grouping the list in groups of two entries, and then using slice notation [::2] and [1::2] to extract the elements and flatten those lists again:
>>> rows = [A_list[i:i+2] for i in range(0, len(A_list), 2)]
>>> x_list = [x for g in rows[::2] for x in g]
>>> y_list = [y for g in rows[1::2] for y in g]
After you silently modified your question (Don't do that; you invalidated most existing answers!) you can now use my 2nd approach, except that your new A_list is now already what rows was there:
>>> x_list = [x for g in A_list[::2] for x in g]
>>> y_list = [y for g in A_list[1::2] for y in g]
You can use slicing syntax to extract the required items and then flatten the resulting sub-lists:
x_list = [item for sub in A_list[::2] for item in sub]
y_list = [item for sub in A_list[1::2] for item in sub]
Just a simple loop.
A_list = [[1,2,3,4],[5,6],[3,4,5],[2,3,5],[5,8,9],[10,11],[22,20],[5,7,8]]
x_list = []
y_list = []
V = 0
for A in A_list:
if V % 4 < 2:
x_list.append(A)
else:
y_list.append(A)
V = V + 1
print(x_list, y_list)
Contrary to Python TOOWTDI principle, there are several ways to do it. One possibility is:
x_list = [A_list[i] for i in range(len(A_list)) if i % 4 < 2]
y_list = [A_list[i] for i in range(len(A_list)) if i % 4 >= 2]
Another:
rows = [ A_list[i:i+4] for i in range(0, len(A_list), 4)]
x_list = [x for row in rows for x in row[0:2]]
y_list = [x for row in rows for x in row[2:4]]
Both the solutions above are for the original problem (before it was modified). For solutions to the problem as it stands now see here.
If you are assuming that there are only two columns in each row then you can do something like this:
A_list = [[1,2,3,4],[5,6],
[3,4,5],[2,3,5],
[5,8,9],[10,11],
[22,20],[5,7,8]]
x_list = []
y_list = []
for x in range(len(A_list))[::4]:
x_list.append(A_list[x])
x_list.append(A_list[x + 1])
y_list.append(A_list[x + 2])
y_list.append(A_list[x + 3])
Note: This only works if the number of columns is two. If the number of columns is not always two or another set number this is a difficult task as the Python list
x_list = [[1,2,3,4],[5,6],
[5,8,9],[10,11]]
Is the same as
x_list = [[1,2,3,4],[5,6],[5,8,9],[10,11]]
This will work for any amount of inputs.
You can achieve this with slicing alone and no conditionals like so:
A_list = [[1,2,3,4],[5,6],
[3,4,5],[2,3,5],
[5,8,9],[10,11],
[22,20],[5,7,8]]
x_list = A_list[::4] + A_list[1::4]
y_list = A_list[2::4] + A_list[3::4]
print(x_list) # [[1, 2, 3, 4], [5, 8, 9], [5, 6], [10, 11]]
print(y_list) # [[3, 4, 5], [22, 20], [2, 3, 5], [5, 7, 8]]
But it does not preserve the order. If that is important to you go with one of the other solutions posted.

Categories

Resources