考虑以下3 x 4矩阵实现为Python中3个长度为4的列表的列表:
>>> matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
以下列表理解将重新排列矩阵转置行和列:
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
但是假设我需要这个结果:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
这是一个重新排列的4 x 3矩阵,以便获得原始矩阵的顺序“滚动”,每3个元素“中断”到一个新行。
我知道可以绘制一个算法来完成任务,但是是否可以仅使用列表推导来获得它?(如果是的话,怎么做?)
修改
接受的答案应符合以下要求:
第二次EDIT +接受的答案动机:
以下是我必须为此找到解决方案时所做的事情(根据我在下面的评论中提出的建议):
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)]
请注意,我写的解决方案是针对这种情况的,但是,正如Clodion所注意到的那样,“公式”可以“推广”,以便将初始(列表列表)矩阵重新排列为不同的“形状” ”
答案 0 :(得分: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)]
如果您想要列表清单:
>>> 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]]
说明:
首先我们创建一个生成器,它给出列表的元素(好像它被展平为一个列表 - 即1,2,3,4,5,6,...,12) - 我们将其存储在it
。
然后我们致电zip()
给它it
三次;由于生成器是相同的,它每次都在it
中提供下一个元素。
进一步说明:如果需要,您甚至可以通过简单地将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]]
答案 1 :(得分:2)
numpy是一个选项吗?
import numpy
x = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
y = numpy.array(x).reshape((4, 3))
print y
输出:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
这里至少有一个列表理解,我现在缺乏创造力,但这有点诀窍:P
print [[[z for y in x for z in y][i*3+j] for j in range(len(x))] for i in range(len(x[0]))]
输出:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
答案 2 :(得分:2)
以下解决方案仅使用列表推导,而不使用zip:
m = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
flat = [l2 for l1 in m for l2 in l1]
output = [[flat.pop(0), flat.pop(0), flat.pop(0)] for x in range(4)]
print(output)
输出是:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
或者对于一个非常简单的一个班轮:
print [m[0][:3],[m[0][3]]+m[1][0:2],m[1][2:]+[m[2][0]],m[2][1:]]
答案 3 :(得分:1)
嗯,只有列表,它很粗糙(建议会受到赞赏吗?):
matrix = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]
lst = [y for row in matrix for y in row]
lst = [[lst[x+y*3] for x in range(3)] for y in range(4)]
print(lst)
结果:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
是的!在一个列表理解中:
nr, nc = 4, 3
ic = len(matrix[0])
lst = [[matrix[(r*nc+c)//ic][(r*nc+c)%ic] for c in range(nc)] for r in range(nr)]
print(*lst, sep="\n")
结果:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10, 11, 12]
但你也可以(nr, nc = 6, 2
)
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9, 10]
[11, 12]
那是你的问题,不是吗?