使用Python中的列表进行矩阵顺时针旋转90度

4
我正在尝试在Python中将一个3×3的矩阵顺时针旋转90度。 我已经确定了[i][j]元素会移动到[j][new_i]。 这里,new_i取决于之前的i,所以我写了一个叫做“循环减法”的函数来实现它。

如果 i 是 0,则 new_i 为 2

如果 i 是 1,则 new_i 为 1

如果 i 是 2,则 new_i 为 0

执行后,程序给出了意外的结果。

我已经打印出每次迭代中发生的所有事情。 但我无法弄清楚为什么有些元素会被替换成不同的值。

'''
1 2 3                       7 4 1
4 5 6  rotate 90 degrees    8 5 2
7 8 9                       9 6 3


'''

def circular_subtraction(i):
    new_i = i 
    if(i==0):
        new_i = 2
    elif(i==1):
        new_i = 1
    elif(i==2):
        new_i = 0
    return new_i


def rotate_clock(matrix):
    new_matrix = matrix

for i in range(len(matrix)):
    for j in range(len(matrix)):
        new_i = circular_subtraction(i)
        new_matrix[j][new_i] = matrix[i][j]
        print("New element added from {},{} to {},{} ::: {} to {}".format(i+1,j+1,j+1,new_i+1,matrix[i][j],new_matrix[j][new_i]))

for each_row in new_matrix:
    print(each_row)




matrix = [[1,2,3],[4,5,6],[7,8,9]]
print("Length of the matrix : ",len(matrix))
for each_row in matrix:
    print(each_row)
print()
matrix = rotate_clock(matrix)

输入矩阵如下:

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

预期结果是:
[7, 4, 1]
[8, 5, 2]
[9, 6, 3]

结果是:

[7, 4, 1]
[2, 5, 2]
[1, 2, 1]

请尝试指出上述代码中的错误。我知道可以很容易地使用numpy完成,但我想手动尝试一下。 - Husain
7个回答

9
你可以像这样做:

你可以这样操作:

matrix = [[1, 2, 3],
          [4, 5, 6],
          [7, 8, 9]]

rotated = [list(reversed(col)) for col in zip(*matrix)]

for row in rotated:
    print(*row)

输出

7 4 1
8 5 2
9 6 3
for col in zip(*matrix) 会获取矩阵的列,一旦获得列,您需要使用 list(reversed(col)) 来反转它们,然后使用列表推导式将它们全部放在一起:
rotated = [list(reversed(col)) for col in zip(*matrix)]

上述列表推导式等同于以下不太“pythonic”的for循环:
rotated = []
for col in zip(*matrix):
    rotated.append(list(reversed(col)))

更多信息

  1. 关于zipreversedlist的文档。
  2. 符号*matrix被称为元组解包,更多信息请参见此处

所以我们旋转每一列,然后将其转换为行? - Husain
是的,您可以获取每一列,将其反转并转换为一行。 - Dani Mesejo
1
太棒了。 - Husain
如何逆时针做? - Abby Chau Yu Hoi

5
你可以使用numpy中的rot90函数来实现此功能:np.rot90
mat = [[1, 2, 3], [4,5,6,], [7,8,9]]
np.rot90(mat, k=1, axes=(1,0))

k - 表示旋转次数
axes - 表示旋转方向

输出

array([[7, 4, 1],
   [8, 5, 2],
   [9, 6, 3]])

你的代码问题

代码缺少缩进(但假设它们是正确的)
这一行:

new_matrix = matrix

为矩阵变量分配一个新的引用。
在Python中,默认情况下不是按值复制。您可以使用深度复制函数:copy.deepcopy(x[, memo])

import copy

def rotate_clock(matrix):
    new_matrix = copy.deepcopy(matrix)

或者

def rotate_clock(matrix):
    new_matrix = [row[:] for row in matrix]

否则,你对new_matrix所做的每个更改都会反映在原始矩阵中。(因为new_matrix只是指向matrix的引用)

谢谢。这就是我想要的。 - Husain

2
在非常简单的Python中,这段代码是有效的:
def rotate_matrix(a):
    b = []
    i = len(a)-1
    while i>=0:
        for j in range(0, len(a)):
            if (len(b) < (j+1)):
                b.append([a[i][j]])
            else:
                b[j].append(a[i][j])
        i -= 1
    return b

我打印了b。它看起来像这样:[[7, 4, 1], [8, 5, 2], [9, 6, 3]]

1

numpy.rot90也很方便:

import numpy as np

a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]
a_rot = np.rot90(a, k=3).tolist()
for row in a_rot:
  print(row)

输出

[7, 4, 1]
[8, 5, 2]
[9, 6, 3]

1

一种通用的方法来旋转矩阵,无论其形状如何。

import numpy as np
A=np.array([[1, 2, 3, 33], [4, 5, 6, 66], [7, 8, 9, 99]])
A
array([[ 1,  2,  3, 33],
       [ 4,  5,  6, 66],
       [ 7,  8,  9, 99]])

rotated_A=np.zeros((len(A[0]),len(A)))
for i in range(len(A)):
    for j in range(len(A[0])):
        rotated_A[j][len(A)-1-i]=A[i][j]
rotated_A
array([[  7.,   4.,   1.],
       [  8.,   5.,   2.],
       [  9.,   6.,   3.],
       [ 99.,  66.,  33.]])

0

通常所有的解决方案都是针对方阵的, 下面这个适用于任何矩阵:

mat = [[1, 2, 3, 5],
     [5, 6, 7, 1],
     [9, 10, 11, 8],
     [4, 7, 4, 3]]
 
def rotate_matrix(a):
    b = []
    i = len(a)-1
    while i>=0:
        if len(a) == len(a[-1]):
            for j in range(0, len(a)):
                print(j)
                if (len(b) < (j+1)):
                    b.append([a[i][j]])
                    print(b)
                else:
                    b[j].append(a[i][j])
                    print(b)
            i -= 1
        else:
            for j in range(0, len(a)+1):
                print(j)
                if (len(b) < (j+1)):
                    b.append([a[i][j]])
                    print(b)
                else:
                    b[j].append(a[i][j])
                    print(b)
            i -= 1
    return b
    
print(rotate_matrix(mat))

0
一个简单的旋转矩阵的解决方案是:
import copy
def rotateImage(a):
 out = copy.deepcopy(a)
 x = 0;
 y = 0;
 for i in a:
  l = len(i)
  for j in i:
   out[y][x+l-1] = j
   y += 1
   if(y == l):
    y=0
  x -= 1
 return(out)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接