这个代码片段如何旋转矩阵?

时间:2013-06-18 08:47:52

标签: python

在寻找旋转矩阵的pythonic方法时,我遇到了this回答。但是没有附加说明。我在这里复制了片段:

rotated = zip(*original[::-1])

它是如何运作的?

3 个答案:

答案 0 :(得分:5)

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

[::-1]撤销列表:

>>> rev = lis[::-1]
>>> rev
[[7, 8, 9], [4, 5, 6], [1, 2, 3]]

现在我们在rev的所有项目上使用zip,并将每个返回的元组追加到旋转:

>>> rotated = []
>>> for item in zip(rev[0],rev[1],rev[2]):
...     rotated.append(item)
...     
>>> rotated
[(7, 4, 1), (8, 5, 2), (9, 6, 3)]

zip从传递给它的每个迭代中选择相同索引中的项目(它只运行到最小长度的项目)并将它们作为元组返回。

什么是*

*用于将rev的所有项目解压缩到zip,因此不会手动输入 rev[0], rev[1], rev[2],我们只需zip(*rev)

上述zip循环也可以写成:

>>> rev = [[7, 8, 9], [4, 5, 6], [1, 2, 3]]
>>> min_length = min(len(x) for x in rev)  # find the min length among all items
>>> rotated = []

for i in xrange(min_length):        
    items = tuple(x[i] for x in rev)  # collect items on the same index from each
                                      # list inside `rev`  
    rotated.append(items)
...     
>>> rotated
[(7, 4, 1), (8, 5, 2), (9, 6, 3)]

答案 1 :(得分:5)

Ashwini和HennyH的解释的补充,这里有一个小图来说明这个过程。

enter image description here

  1. 首先,[::-1]切片运算符会反转列表列表,获取整个列表(因此可以省略前两个参数)并使用-1步骤。
  2. 其次,zip函数采用多个列表并有效地返回一个新的列表,其中行和列被反转。 *表示列表列表已解压缩到多个列表中。
  3. 可以看出,这两个操作相结合将旋转矩阵。

答案 2 :(得分:2)

我的探索:

>>> m = [['a','b','c'],[1,2,3]]

当漂亮印刷时会是:

>>> pprint(m)
['a', 'b', 'c']
[1, 2, 3]

首先,zip(*m)将在m中创建所有的列表。如下所示:

>>> zip(*m)
[('a', 1), ('b', 2), ('c', 3)]

这种方法的工作方式是zip获取 n 序列并得到每个<{1}}元素并将其添加到元组中。所以转换为我们的矩阵i-th,其中每个m中包含的列表表示,我们基本上将每行传递给m,然后获取每行的第一个元素将所有元素放入一个元组中,然后从每一行获取每个第二个元素等等......最终获得zip中的每个,即:

m

现在看起来像:

>>> zip(['row1column1','row1column2'],['row2column1','row2column2'])
[('row1column1', 'row2column1'), ('row1column2', 'row2column2')]
Notice that each tuple contains all the elements in a specific column

如此有效,>>> pprint(zip(*m)) ('a', 1) ('b', 2) ('c', 3) 中的每个现在都是。然而,它的顺序不正确(试着想象在你的头部旋转m以获得上面的矩阵,它无法完成)。这就是为什么有必要“翻转”原始矩阵:

m

这导致矩阵相当于>>> pprint(zip(*m[::-1])) (1, 'a') (2, 'b') (3, 'c') 旋转 - 90度。