8

在寻找一种旋转矩阵的pythonic方法时,我遇到了这个答案。但是,没有任何解释。我在这里复制了片段:

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

它是如何工作的?

4

3 回答 3

5

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

在此处输入图像描述

  1. 首先,[::-1]切片运算符反转列表列表,获取整个列表(因此可以省略前两个参数)并使用-1.
  2. 其次,该zip函数采用多个列表并有效地返回一个行和列颠倒的新列表。*表示列表列表被解压缩成几个列表。

可以看出,这两个操作结合起来会旋转矩阵。

于 2013-06-18T09:29:23.857 回答
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]]

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

>>> 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从传递给它的每个可迭代对象的同一索引中选择项目(它只运行到具有最小长度的项目)并将它们作为元组返回。

什么是*

*用于解包revto的所有项目,因此我们可以简单地做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)]
于 2013-06-18T08:53:28.763 回答
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 个序列并获取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)

如此有效,现在的每一都是一行。但是它的顺序不正确(试着想象你的头部旋转以获得上面的矩阵,它不能完成)。这就是为什么有必要“翻转”原始矩阵的原因:mm

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

这导致一个矩阵相当于m旋转了 - 90 度。

于 2013-06-18T09:02:35.740 回答