仅使用列表推导重新排列(列表列表)矩阵

dan*_*tra 5 python list-comprehension list matrix

考虑以下 3 x 4 矩阵在 Python 中实现为 3 个长度为 4 的列表:

>>> matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
Run Code Online (Sandbox Code Playgroud)

以下列表推导式将重新排列矩阵转置行和列:

>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Run Code Online (Sandbox Code Playgroud)

但假设我需要这个结果:

[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Run Code Online (Sandbox Code Playgroud)

这是一个重新排列的 4 x 3 矩阵,以获得原始矩阵的顺序“滚动”,每 3 个元素“中断”到一个新行。

我知道有可能制定出一种算法来完成任务,但是否可以仅使用列表推导来获得该算法(而且,如果是,如何?)


编辑:

接受的答案应满足以下要求:

  • 必须在基本/干净的 Python 安装上工作(没有额外的库);
  • 必须(类似于矩阵转置)是“单线”。

第二次编辑 + 接受的答案动机:

当我不得不为此找到解决方案时,这是我所做的(基于我在下面自己的评论中给出的建议):

mat = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

[[mat[(3*(i-1)+j -1)//4+1][(3*(i-1)+j -1)%4] for j in range(3)] for i in range(4)]
Run Code Online (Sandbox Code Playgroud)

请注意,我编写的解决方案特定于这种情况,但正如 Clodion 也注意到的那样,“公式”可以“泛化”,以便将初始(列表列表)矩阵重新排列为不同的“形状”。

Ana*_*mar 3

像这样的事情怎么样:

>>> matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
>>> it = (y for x in matrix for y in x)
>>> list(zip(*[it]*3))
[(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)]
Run Code Online (Sandbox Code Playgroud)

如果你想要列表的列表:

>>> matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
>>> it = (y for x in matrix for y in x)
>>> list(map(list, zip(*[it]*3)))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 首先,我们创建一个生成器,它给出列表的元素(就好像它被展平为单个列表 - 即 1,2,3,4,5,6,...,12) - 我们将其存储在it.

  2. 然后我们称之为zip()it三遍;由于生成器是相同的,因此它it每次都会提供下一个元素。

进一步注意:如果需要,您甚至可以将初始矩阵重新排列为与 4 x 3 不同的“形状”,只需将 更改3为所需的列数即可。(例如,将其更改为26,您将分别获得 6 x 2 或 2 x 6 重新排列的矩阵)。


一种不使用zip,仅使用列表理解的方法,但它需要两行 -

>>> matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
>>> it = (y for x in matrix for y in x)
>>> [[next(it) for _ in range(3)] for _ in range(4)]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Run Code Online (Sandbox Code Playgroud)