在Python中旋转二维数组

2024-05-16 20:33:06 发布

您现在位置:Python中文网/ 问答频道 /正文

在我编写的一个程序中,需要旋转二维数组。在寻找最佳解决方案的过程中,我发现了一条令人印象深刻的直线:

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

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

如果有人能解释一下所涉及的不同功能是如何达到预期效果的,我将不胜感激。


Tags: 程序功能过程数组zip解决方案直线original
3条回答

这有三个部分:

  1. original[::-1]反转原始数组。这个符号是Python列表切片。这将为您提供由[start:end:step]描述的原始列表的“子列表”,start是第一个元素,end是要在子列表中使用的最后一个元素。步骤是从第一步到最后一步的每一个元素。省略start和end意味着片段将是整个列表,而负的步骤意味着元素将相反。例如,如果原始值是[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,并且包含每个原始列表的相应元素。E、 例如,zip([1,2],[a,b],[x,y])是[1,a,x],[2,b,y]]。另见Python documentation.

请考虑以下二维列表:

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

让我们一步一步地分解它:

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

使用argument unpacking将此列表传递到zip()中,因此zip调用最终等同于:

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

希望这些注释清楚地说明了zip的作用,它将根据索引对每个输入iterable中的元素进行分组,或者换句话说,它将列分组。

真聪明。下面是故障:

  • [::-1]-按相反顺序生成原始列表的浅层副本。也可以使用reversed(),这将在列表上生成一个反向迭代器,而不是实际复制列表(更节省内存)。
  • *-使原始列表中的每个子列表成为zip()的单独参数(即,解压缩列表)
  • zip()-从每个参数中提取一个项,并从中生成一个列表(一个元组),然后重复,直到所有子列表都用完为止。这就是真正发生换位的地方。

所以假设你有这个:

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

你首先得到这个(浅的,反拷贝):

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

接下来,每个子列表都作为参数传递给zip

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

zip()从每个参数的开头重复使用一个项并从中生成一个元组,直到没有更多项为止,结果是:

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

鲍勃是你叔叔。

要在注释中回答@IkeMiguel关于将其旋转到另一个方向的问题,非常简单:您只需要反转进入zip的序列和结果。第一个可以通过删除[::-1]来实现,第二个可以通过在整个对象周围抛出reversed()来实现。由于reversed()返回列表上的迭代器,我们需要将list()放在周围以转换它。所以:

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

当然,您也可以将列表顺时针旋转三次。:-)

相关问题 更多 >