雖然尋找pythonic的方式來旋轉矩陣,我碰到了this答案。但是沒有解釋。我在這裏複製了片段:此代碼片段如何旋轉矩陣工作?
rotated = zip(*original[::-1])
它是如何工作的?
雖然尋找pythonic的方式來旋轉矩陣,我碰到了this答案。但是沒有解釋。我在這裏複製了片段:此代碼片段如何旋轉矩陣工作?
rotated = zip(*original[::-1])
它是如何工作的?
>>> 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
上轉的所有項目,並且每個返回的元組追加到旋轉:
>>> 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)]
對於我explination:
>>> 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
需要ñ序列和獲得的每一個的i-th
元素並將其添加到一個元組。所以翻譯成我們的矩陣m
其中每個行由包含在m
內的列表表示,我們基本上將每一行傳遞給zip
,然後從每一行獲得第一個元素,將它們全部放入一個元組中,然後獲得每個第二
>>> 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
即獲得每列列 in m
現在是行。不過,它的順序並不正確(試着想象一下在你的頭上旋轉m
得到上面的矩陣,它不能完成)。這爲什麼它是必要的「炫」原矩陣:
>>> pprint(zip(*m[::-1]))
(1, 'a')
(2, 'b')
(3, 'c')
這會導致基質這是m
旋轉相當於 - 90度。
作爲Ashwini和HennyH解釋的補充,下面是一個小圖來說明這個過程。
[::-1]
切片操作者反轉列表的列表中,將整個列表(因此第一兩個參數可以被省略),並且使用的-1
的步驟。zip
函數需要多個列表並有效地返回一個新列表,其中行和列反轉。 *
表示列表的列表被解壓到幾個列表中。可以看出,這兩種操作相結合會旋轉矩陣。
+1不錯的插圖 – HennyH