3

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.

yatu
  • 86,083
  • 12
  • 84
  • 139
Tom
  • 8,310
  • 2
  • 16
  • 36

1 Answers1

2

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]
yatu
  • 86,083
  • 12
  • 84
  • 139