Given a square matrix represented as a list of lists, you can transpose it:
>>> l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> l_T = list(map(list, zip(*l)))
>>> l_T
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
You can then flatten a list of lists using a list comprehension:
>>> v = [i for j in l for i in j]
>>> v_T = [i for j in l_T for i in j]
>>> v
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> v_T
[1, 4, 7, 2, 5, 8, 3, 6, 9]
My question is, is there a way to take the flattened list version of a square matrix, and rearrange it so it becomes the transposed version? Here, that would be to get from v to v_T without going back through a list of lists. I have tried to map out the relationship between the matrix position and the list indices, but I am not seeing the pattern, let alone one that would generalize to lists of any (square) length.
In order to try to avoid any XY problems: my original goal was to be able to take some simple list of list matrices and iterate over them in different ways (i.e. left>right then top>bottom versus top>bottom then left>right). And if your starting point is l, then it is easy to just create the transpose and unpack. But I am imagining you have the flattened matrix (v) as a starting point, and you want to compute v_T directly. So I am really more curious about that algorithm now, and how to do so in Python.
Start by finding the square root of the lists' length, and take slices of the list iteratively, starting on different lags until you've sliced all columns (or what would be the columns in a transposed 2D array):
def transpose_flat_list(l):
n = int(len(l)**.5)
return [v for i in range(n) for v in l[i::n]]
For the shared example:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
transpose_flat_list(l)
# [1, 4, 7, 2, 5, 8, 3, 6, 9]
This could easily be done in NumPy too by reshaping and raveling in fortran order as:
def transpose_flat_list_numpy(l):
n = int(len(l)**.5)
return np.array(l).reshape(n,n).ravel('F').tolist()
transpose_flat_list_numpy(l)
# [1, 4, 7, 2, 5, 8, 3, 6, 9]
Related
I want to know how I can add a value to each element of a NXN multidimensional array. I tried [x+1 for x in multiArray], but this one yields only for a 1D array.
Maybe something like this:
multiArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
addingArray=[]
for i in range(3):
for j in range(3):
addingArray.append(multiArray[j]+1) #(adding 1 to each element here)
But this seems to be wrong?
You're getting 1D array as result because you have addingArray as a simple list. So, you iterate over all the elements in your multiArray and add 1 to it and you're appending the result to a list.
For efficiency reasons, it is advisable to use NumPy for arrays. Then, you can simply use broadcasting to add value to each element of the array. Below is an illustration:
# input array
In [180]: multiArray = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# add 1 to each value of the array
In [181]: multiArray + 1
Out[181]:
array([[ 2, 3, 4],
[ 5, 6, 7],
[ 8, 9, 10]])
If you indeed want a plain python list as the result for some reasons, you can simply cast it to one:
In [182]: (multiArray + 1).tolist()
Out[182]: [[2, 3, 4], [5, 6, 7], [8, 9, 10]]
Indice-iteration
You need to have a inner list to get the inner results, and access the good value with multiArray[i][j], also don't use constant 3 take the habit to use object length
addingArray=[]
for i in range(len(multiArray)):
innerArray = []
for j in range(len(multiArray[i])):
innerArray.append(multiArray[i][j]+1)
addingArray.append(innerArray)
print(addingArray) # [[2, 3, 4], [5, 6, 7], [8, 9, 10]]
Value iteration
You can also iterate over the arra directly to simplify and don't both with indices
addingArray=[]
for inner in multiArray:
innerArray = []
for value in inner:
innerArray.append(value+1)
addingArray.append(innerArray)
List comprehension
And shorten it with list comprehension syntax
multiArray = [[v+1 for v in inner] for inner in multiArray]
print(multiArray) # [[2, 3, 4], [5, 6, 7], [8, 9, 10]]
For the program I am writing my goal is to call a function, give it 2 values and then have it spit back lists based on those 2 numbers. Here's what I have so far,
import numpy as np
def list_maker (n, m):
for n in range(n):
l = list(np.random.randint(1,9, m))
print(l)
My goal is to type "list_maker(3,5)" and have it output 3 lists, each with 5 elements. I want to keep using numpy so I can learn more about it rather than another type of operation. Whenever I call the function my out it,
list_maker(3,5)
[2, 7, 1, 5, 6]
[8, 5, 1, 3, 5]
[8, 2, 6, 3, 7]
However, I can not specifically change one element in one list, if I do l[0] = "Blank", all the elements at 0 position turn to blank and I can't do [0],[1]....
Any idea how to get an output like,
list_maker(3,5)
[[2, 7, 1, 5, 6],
[8, 5, 1, 3, 5],
[8, 2, 6, 3, 7]]
Where I can then specifically edit one element in one of the lists done by numpy?
Thank you for all the replies!
you want to return a list of lists. A simple list comprehension would work:
import numpy as np
def list_maker (n, m):
return [list(np.random.randint(1,9, m)) for _ in range(n)]
then:
>>> list_maker(3,5)
[[1, 7, 2, 5, 7], [3, 5, 5, 7, 7], [8, 5, 1, 1, 1]]
At the moment your function is just printing the lists and not returning them.
And I'm not entirely sure of your intent; at the moment you're not creating a numpy array, but a list. More specifically, you're creating a list of 3 lists, not 3 separate lists.
You could create a numpy array by passing the n, m values directly to numpy's randint:
np.random.randint(1,9, size=(n, m))
This question already has an answer here:
Create index list for np.split from the list that already has number for each section
(1 answer)
Closed 3 years ago.
Let's say I've got an array [0, 1, 2, 3, 4, 5, 6, 7] and a tuple: (3, 3, 2).
I'm looking for a way to split my array to 3 array based on my tuple data:
[0, 1, 2]
[3, 4, 5]
[6, 7]
I can write a simple code like this to get what I want, however I'm looking for a correct and pythonic way to do this:
I used lists for simplicity.
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = []
for j in range(i):
lst.append(a[pointer])
pointer += 1
print(lst)
Or this one:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = a[pointer:pointer+i]
pointer += i
print(lst)
Results:
[0, 1, 2]
[3, 4, 5]
[6, 7]
you can use the split method of numpy
import numpy as np
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
c = np.split(a, np.cumsum(b)[:-1])
for r in c:
print(r)
np.split(a, b) splits a by the indices in b along a given axis(0 by default).
If you don't want to modify your input list, you can use an iterator and the itertools module.
>>> from itertools import islice
>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> b = (3, 3, 2)
>>> i = iter(a)
>>> [list(islice(i, x)) for x in b]
[[0, 1, 2], [3, 4, 5], [6, 7]]
In the first step you create an iterator, which starts at the first element of a. Then you iterate in a list comprehension over your numbers in b and in each step you pull accordingly many elements from the iterator and store them in your result list.
One simpler way is this:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
for ind in b:
print(a[:ind])
a = a[ind:]
It loops through slice sizes in b while shortening the original array every time. You can easily append the resulting slices as sublists if you need them for something else. It's almost like one of your solutions except it doesn't use any extra variables and iterates directly through elements of b.
Also, I wouldn't call variables a and b - surely not in this case where variables have clear meanings that you can express through their names. More meaningful names lessen bugs number and make code more clear, becomes a real difference with larger/more complex code. I'd call a at least in_list and b slices, but with more context this could be better.
The most "concise" syntax would be :
ex_array = [0, 1, 2, 3, 4, 5, 6, 7]
extuple = (3, 3, 2)
result = [ex_array[sum(extuple[:iii]):sum(extuple[:iii])+extuple[iii]] for iii in range(len(extuple))]
result would be a list of the expected sub-lists
Re-using the pairwise function from Compare two adjacent elements in same list, you could also:
from itertools import accumulate
from more_itertools import pairwise
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
[a[slice(*s)] for s in pairwise(accumulate((0,)+b))]
That begin said, the np.split answer is probably faster (and easier to read).
I would like a list to be stored into another list from right to left diagonally without importing anything if possible
eg. list =
[[1, 4, 6]
[6, 3, 7]
[2, 7, 9]]
say I'd like to store [6, 3, 2] into another list, how would i go about doing it? I have tried many ways for hours and still cant find a solution
With a list comprehension:
l =[[1, 4, 6],
[6, 3, 7],
[2, 7, 9]]
diagonal = [row[-i] for i, row in enumerate(l, start=1)]
print(diagonal)
Output
[6, 3, 2]
The following snipped
l =[[1, 4, 6],
[6, 3, 7],
[2, 7, 9]]
d = len(l)
a = []
for i in range(0,d):
a.append(l[i][d-1-i])
print(a)
results in the output you expected:
[6, 3, 2]
You can use a list comprehension and use list indexing twice to select your row and column:
L = [[1, 4, 6],
[6, 3, 7],
[2, 7, 9]]
n = len(L)
res = [L[i][n-i-1] for i in range(n)]
# [6, 3, 2]
An alternative formulation is to use enumerate as per #OlivierMelançon's solution.
If you can use a 3rd party library, you can use NumPy to extract the diagonal of a flipped array:
import numpy as np
arr = np.array(L)
res = np.diag(np.fliplr(arr))
# array([6, 3, 2])
When you want to create a list out from another list, list comprehension is a very good way to go.
a = yourlist
print([a[i][(i+1)*-1] for i in range(len(a))])
This list comprehension loops through the lists taking the the furthes back integer and the second furthes back and so on.
Using numpy and rotate (90)
import numpy as np
list = [[1, 4, 6],[6, 3, 7],[2, 7, 9]]
np.diag(np.rot90(array))
Output :
array([6, 3, 2])
or without using numpy:
list = [[1, 4, 6],[6, 3, 7],[2, 7, 9]]
res=[]
i=-1
for elm in list :
res.append(elm[i])
i-=1
print res
#[6, 3, 2]
I have the following array [1, 4, 7, 9, 2, 10, 5, 8] and I need to separate the array in 3 different arrays: one for values between 0 and 3, anther for 3 to 6 and anther for 6 and 25.The result must be something like that:
array1 = [1, 2]
array2 = [4, 5]
array3 = [7, 9, 10, 8]
Any idea about how to do it simple?
First, define your "pole" numbers
Second, generate your intervals from those "pole" numbers
Third, define as many lists as there are intervals.
Then for each interval, scan the list and appends items in the relevant list if they belong to the interval
code:
source = [1, 4, 7, 9, 2, 10, 5, 8]
poles = (0,3,6,25)
intervals = [(poles[i],poles[i+1]) for i in range(len(poles)-1)]
# will generate: intervals = [(0,3),(3,6),(6,25)]
output = [list() for _ in range(len(intervals))]
for out,(start,stop) in zip(output,intervals):
for s in source:
if start <= s <stop:
out.append(s)
print(output)
result:
[[1, 2], [4, 5], [7, 9, 10, 8]]
This solution has the advantage of being adaptable to more than 3 lists/intervals by adding more "pole" numbers.
EDIT: There's a nice & fast solution (O(log(N)*N)) if the output lists order don't matter:
first sort the input list
then generate the sliced sub-lists using bisect which returns insertion position of the provided numbers (left & right)
like this:
import bisect
source = sorted([1, 4, 7, 9, 2, 10, 5, 8])
poles = (0,3,6,25)
output = [source[bisect.bisect_left(source,poles[i]):bisect.bisect_right(source,poles[i+1])] for i in range(len(poles)-1)]
print(output)
result:
[[1, 2], [4, 5], [7, 8, 9, 10]]
You can do that in a very simple way using a combination of a for loop and range functions:
lists = ([], [], [])
for element in [1, 4, 7, 9, 2, 10, 5, 8]:
if element in range(0, 3):
lists[0].append(element)
elif element in range(3, 6):
lists[1].append(element)
elif element in range(6, 25):
lists[2].append(element)
array1, array2, array3 = lists
"One-line" solution using set.intersection(*others) and range(start, stop[, step]) functions:
l = [1, 4, 7, 9, 2, 10, 5, 8]
l1, l2, l3 = (list(set(l).intersection(range(3))), list(set(l).intersection(range(3,6))), list(set(l).intersection(range(6,25))))
print(l1)
print(l2)
print(l3)
The output:
[1, 2]
[4, 5]
[8, 9, 10, 7]
https://docs.python.org/3/library/stdtypes.html?highlight=intersection#set.intersection