python取矩阵的一部分,Python:如何转置矩阵的一部分

If I have a matrix like this:

matrix = [[1, 2, 3, 4],

[5, 6, 7, 8],

[9, 10, 11, 12],

[13, 14, 15, 16]]

how can I get this:

matrix = [[1, 2, 3, 4],

[5, 6, 10, 14],

[9, 7, 11, 15],

[13, 8, 12, 16]]

That is, how can I exclude the first row and the first column and

transpose the rest?

I tried this, it leaves the matrix unchanged:

for i in range(1, 4):

for j in range(1, 4):

temp = copy.deepcopy(matrix[i][j])

matrix[i][j] = matrix[j][i]

matrix[j][i] = temp

And when I try:

new_matrix = list(matrix)

for i in range(1, 4):

for j in range(1, 4):

matrix[i][j] = new_matrix[j][i]

matrix[j][i] = new_matrix[i][j]

I get this:

[[1, 2, 3, 4],

[5, 6, 10, 14],

[9, 10, 11, 15],

[13, 14, 15, 16]]

I want to transpose it over both the main and the secondary diagonal.

解决方案

When in doubt, write a function.

Ever wondered why Python lacks a built-in function for transposing matrices? It's because zip does it already. But zip returns a sequence of tuples, and you need lists, so let's wrap it up.

def transpose(matrix):

return [list(row) for row in zip(*matrix)]

We need to transpose a sub-matrix. How do we extract it?

def submatrix(matrix, skip=1):

return [row[skip:] for row in matrix[skip:]]

It turns out we'll need a function to paste contents of one list over the contents of another, bigger list. The function below assumes that the smaller overlay list never gets past the bounds of the bigger base list, for the sake of simplicity.

def pasteOver(base, overlay, offset):

"""Paste overlay list over base list, starting at offset.

Works even when overlay is not touching either end of base."""

return base[:offset] + overlay + base[(len(overlay)) + offset:]

This picture hopefully helps understand why the indexes in the above code are what they are. The blue part is the overlay, the longer colored part is base; the part which will be overlaid is grayed out.

34c623e5dceefc3d0bc9cf595a3351c4.png

The red part does not occur in your problem, but it's added to make the code a more general solution; it's the base[(len(overlay)) + offset:] part.

I hope you know how Python's list slicing works.

Now we can paste an entire matrix over another, bigger matrix, by pasting changed rows over it, and pasting a submatrix row over any changed row. Note how the code below is almost a literal translation of the previous sentence.

def graft(matrix, submatrix, offset):

"""Overlays submatrix on matrix at given offset from top/left."""

changing_rows = matrix[offset : offset + len(submatrix)]

changed_rows = [pasteOver(row, sub_row, offset)

for (row, sub_row) in zip(changing_rows, submatrix)]

return pasteOver(matrix, changed_rows, offset)

Now it's easy to combine things to paste a transposed submatrix:

def subTranspose(matrix, skip=1):

sub_transposed = transpose(submatrix(matrix, skip))

return graft(matrix, sub_transposed, skip)

Note how every function is almost comically short and simple, so that "its correctness is painfully obvious" (q). Also note how every function is pure, it never changes the data passed to it or has any other side effects. This code, were it in a real code base, would be easier to read, test, reuse, and maintain.

(But if your matrices are really big, use numpy anyway.)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值