在一个程序中,我写的是需要旋转一个二维数组。寻找最佳解决方案我发现了这个令人印象深刻的单线工作:
rotated = zip(*original[::-1])
我现在正在我的程序中使用它,它可以正常运行。我的问题是,我不明白它是如何工作的。
如果有人能解释所涉及的不同功能如何达到预期效果,我将不胜感激。
答案 0 :(得分:74)
这是一个聪明的位。这是细分:
[::-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)))
当然,您也可以简单地顺时针旋转列表三次。 : - )
答案 1 :(得分:71)
考虑以下二维列表:
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
的作用,它会根据索引对每个输入可迭代的元素进行分组,或者换句话说,它将列分组。
答案 2 :(得分:14)
这有三个部分:
答案 3 :(得分:7)
只是一个观察。输入是一个列表列表,但非常好的解决方案的输出:rotating = zip(* original [:: - 1])返回一个元组列表。
这可能是也可能不是问题。
然而,这很容易纠正:
original = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
def rotated(array_2d):
list_of_tuples = zip(*array_2d[::-1])
return [list(elem) for elem in list_of_tuples]
# return map(list, list_of_tuples)
print(list(rotated(original)))
# [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
list comp或map都会将内部元组转换回列表。
答案 4 :(得分:1)
我自己遇到过这个问题,我找到了关于这个主题的精彩维基百科页面(在“共同轮换”段落中: https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities
然后我编写了以下代码,超级详细,以便清楚地了解正在发生的事情。
我希望你会发现在你发布的非常漂亮和聪明的单行中挖掘更多内容是有用的。
要快速测试,您可以在此处复制/粘贴:
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 "=== === === === === === === === === "
答案 5 :(得分:1)
def ruota_antiorario(matrix):
ruota=list(zip(*reversed(matrix)))
return[list(elemento) for elemento in ruota]
def ruota_orario(matrix):
ruota=list(zip(*reversed(matrix)))
return[list(elemento)[::-1] for elemento in ruota][::-1]
答案 6 :(得分:0)
逆时针旋转(标准列到行枢轴)为列表和字典
df_out = df_a.join([df_b], how='outer').reindex(index)
Out[1068]:
Temperature Humidity Pressure
2019-05-25 10:00:00 25.0 60.0 NaN
2019-05-25 10:05:00 26.0 25.0 1020.0
2019-05-25 10:10:00 27.0 63.0 1021.0
2019-05-25 10:15:00 NaN NaN 1019.0
2019-05-25 10:20:00 28.0 62.0 NaN
产生:
rows = [
['A', 'B', 'C', 'D'],
[1,2,3,4],
[1,2,3],
[1,2],
[1],
]
pivot = []
for row in rows:
for column, cell in enumerate(row):
if len(pivot) == column: pivot.append([])
pivot[column].append(cell)
print(rows)
print(pivot)
print(dict([(row[0], row[1:]) for row in pivot]))
答案 7 :(得分:-3)
我正在练习python嵌套列表推导并编写以下代码以返回矩阵中的列列表,这类似于旋转矩阵:
def getColumns(matrix):
columns = [[row[col] for row in matrix] for col in range(len(matrix[1]))]
return columns