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 个元素“中断”到一个新行。
我知道有可能制定出一种算法来完成任务,但是否可以仅使用列表推导来获得该算法?(而且,如果是,如何?)
编辑:
接受的答案应满足以下要求:
第二次编辑 + 接受的答案动机:
当我不得不为此找到解决方案时,这是我所做的(基于我在下面自己的评论中给出的建议):
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 也注意到的那样,“公式”可以“泛化”,以便将初始(列表列表)矩阵重新排列为不同的“形状”。
像这样的事情怎么样:
>>> 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,2,3,4,5,6,...,12) - 我们将其存储在it
.
然后我们称之为zip()
给it
三遍;由于生成器是相同的,因此它it
每次都会提供下一个元素。
进一步注意:如果需要,您甚至可以将初始矩阵重新排列为与 4 x 3 不同的“形状”,只需将 更改3
为所需的列数即可。(例如,将其更改为2
或6
,您将分别获得 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)