在Python中旋转二维数组

在一个程序中,我写了旋转一个二维数组的需求。 寻找最佳的解决scheme我发现这个令人印象深刻的单线程来完成这项工作:

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

我正在使用它在我的程序中,它的工作原理。 我的问题,但是,我不明白它是如何工作的。

我会很感激,如果有人可以解释如何涉及不同的function达到预期的结果。

考虑下面的二维列表:

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

让我们一步一步分解:

 >>> original[::-1] # elements of original are reversed [[3, 4], [1, 2]] 

这个列表使用参数解包传递给zip() ,所以zip调用结束与此等效:

 zip([3, 4], [1, 2]) # ^ ^----column 2 # |-------column 1 # returns [(3, 1), (4, 2)], which is a original rotated clockwise 

希望这些注释可以清楚地说明zip所做的事情,它会根据索引对每个input迭代的元素进行分组,或者换句话说就是对列进行分组。

这是一个聪明点。 这是细节:

  • [::-1] – 以相反顺序制作原始列表的浅表副本。 也可以使用reverse reversed() ,它会在列表上生成一个反向迭代器,而不是实际上复制列表(更高的内存效率)。
  • * – 使原始列表中的每个子列表都有一个独立的参数( zip() (即解压列表)
  • zip() – 从每个参数中取一个项目,并从这些项目列出一个列表(以及一个元组),然后重复,直到所有的子列表都耗尽。 这是换位的地方。

所以假设你有这个:

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

你首先得到这个(浅的,颠倒的):

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

接下来,每个子列表都作为parameter passing给zip

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

zip()从其每个参数的开始处反复消耗一个项目,并从中创build一个元组,直到不再有项目,导致:

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

而鲍勃是你的叔叔。

为了回答@ IkeMiguel的问题,在关于向另一个方向旋转它的评论中,这是非常简单的:你只需要反转进入zip的序列和结果。 第一个可以通过移除[::-1]来实现,第二个可以通过在整个事物上抛出reversed()来实现。 由于reversed()在列表上返回一个迭代器,所以我们需要放置list()来转换它。 所以:

 rotated = list(reversed(zip(*original))) 

当然,你也可以简单的顺时针旋转列表三次。 🙂

这有三个部分:

  1. 原始[:: – 1]反转原始数组。 这个符号是Python列表切片。 这给你一个由[start:end:step]描述的原始列表的“子列表”,start是第一个元素,end是在子列表中使用的最后一个元素。 一步一步说从每一步开始。 忽略开始和结束意味着切片将是整个列表,而负的步骤意味着您将获得相反的元素。 所以,例如,如果original是[x,y,z],结果是[z,y,x]
  2. 当在函数调用的参数列表中前面的一个列表/元组时,意味着“扩展”列表/元组,使得它的每个元素成为函数的一个单独的参数,而不是列表/元组本身。 因此,如果参数args = [1,2,3],则zip(args)与zip([1,2,3])相同,但zip(* args)与zip(1, 2,3)。
  3. zip是一个函数,它接受n个参数,每个参数的长度为m,并产生一个长度为m的列表,长度为n的元素包含每个原始列表的相应元素。 例如,zip([1,2],[a,b],[x,y])是[[1,a,x],[2,b,y]]。 另请参阅Python文档。

我自己也遇到了这个问题,并且find了关于这个主题的伟大维基百科页面(在“常见旋转”一段中:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities

然后,我写了下面的代码,超级冗长,以便清楚地了解正在发生的事情。

我希望你会发现在你发布的非常漂亮和巧妙的一行中挖掘更多的东西是有用的。

要快速testing它,你可以复制/粘贴在这里:
http://www.codeskulptor.org/

 triangle = [[0,0],[5,0],[5,2]] coordinates_a = triangle[0] coordinates_b = triangle[1] coordinates_c = triangle[2] def rotate90ccw(coordinates): print "Start coordinates:" print coordinates old_x = coordinates[0] old_y = coordinates[1] # Here we apply the matrix coming from Wikipedia # for 90 ccw it looks like: # 0,-1 # 1,0 # What does this mean? # # Basically this is how the calculation of the new_x and new_y is happening: # new_x = (0)(old_x)+(-1)(old_y) # new_y = (1)(old_x)+(0)(old_y) # # If you check the lonely numbers between parenthesis the Wikipedia matrix's numbers # finally start making sense. # All the rest is standard formula, the same behaviour will apply to other rotations, just # remember to use the other rotation matrix values available on Wiki for 180ccw and 170ccw new_x = -old_y new_y = old_x print "End coordinates:" print [new_x, new_y] def rotate180ccw(coordinates): print "Start coordinates:" print coordinates old_x = coordinates[0] old_y = coordinates[1] new_x = -old_x new_y = -old_y print "End coordinates:" print [new_x, new_y] def rotate270ccw(coordinates): print "Start coordinates:" print coordinates old_x = coordinates[0] old_y = coordinates[1] new_x = -old_x new_y = -old_y print "End coordinates:" print [new_x, new_y] print "Let's rotate point A 90 degrees ccw:" rotate90ccw(coordinates_a) print "Let's rotate point B 90 degrees ccw:" rotate90ccw(coordinates_b) print "Let's rotate point C 90 degrees ccw:" rotate90ccw(coordinates_c) print "=== === === === === === === === === " print "Let's rotate point A 180 degrees ccw:" rotate180ccw(coordinates_a) print "Let's rotate point B 180 degrees ccw:" rotate180ccw(coordinates_b) print "Let's rotate point C 180 degrees ccw:" rotate180ccw(coordinates_c) print "=== === === === === === === === === " print "Let's rotate point A 270 degrees ccw:" rotate270ccw(coordinates_a) print "Let's rotate point B 270 degrees ccw:" rotate270ccw(coordinates_b) print "Let's rotate point C 270 degrees ccw:" rotate270ccw(coordinates_c) print "=== === === === === === === === === " 

我正在练习Python嵌套列表parsing,并编码以下内容以返回matrix中的列表,这类似于旋转matrix:

 def getColumns(matrix): columns = [[row[col] for row in matrix] for col in range(len(matrix[1]))] return columns 
 import copy def rotate(matrix): data = copy.deepcopy(matrix) for i in range(len(data)): for j in range(i+1,len(data[i])): temp=data[i][j] data[i][j]=data[j][i] data[j][i]=temp return data