回答:
次の2次元リストを考えてみます。
original = [[1, 2],
[3, 4]]
それを段階的に分解してみましょう:
>>> original[::-1] # elements of original are reversed
[[3, 4], [1, 2]]
このリストは引数unpackingをzip()
使用して渡されるため、呼び出しは最終的にこれzip
と同等になります。
zip([3, 4],
[1, 2])
# ^ ^----column 2
# |-------column 1
# returns [(3, 1), (4, 2)], which is a original rotated clockwise
うまくいけば、コメントで何zip
が行われるかが明確になり、インデックスに基づいて反復可能な各入力の要素がグループ化されます。つまり、列がグループ化されます。
rotated = [list(r) for r in zip(*original[::-1])]
それは賢いビットです。
まず、コメントで述べたように、Python 3 zip()
ではイテレーターを返すlist()
ため、実際のリストを取り戻すには全体を囲む必要があります。2020年の時点では、実際には次のようになります。
list(zip(*original[::-1]))
内訳は次のとおりです。
[::-1]
-元のリストの浅いコピーを逆の順序で作成します。も使用できますreversed()
実際にリストをコピーするのではなく、リストに対してリバースイテレータを生成 whichをすることます(よりメモリ効率が良い)。*
-元のリストの各サブリストを別の引数にします zip()
(つまり、リストをアンパックします)zip()
-各引数から1つの項目を取り、それらからリスト(まあ、タプル)を作成し、すべてのサブリストがなくなるまで繰り返します。これが実際に移調が発生する場所です。list()
の出力を変換します 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()
は、各引数の先頭から1つのアイテムを繰り返し消費し、アイテムがなくなるまでタプルを作成し、(リストに変換された後)結果として次のようになります。
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
そしてボブはあなたの叔父です。
@IkeMiguelの反対方向への回転についてのコメントでの質問に答えるには、それは非常に簡単ですzip
。入るシーケンスと結果の両方を逆にするだけです。1つ目はを削除する[::-1]
ことで実現でき、2つ目reversed()
は全体をスローすることで実現できます。以来reversed()
、リストの上に返すイテレータ、我々は配置する必要がありますlist()
周りのこと、それを変換します。list()
イテレータを実際のリストに変換するための追加の呼び出しがいくつかあります。そう:
rotated = list(reversed(list(zip(*original))))
「火星のスマイリー」スライスを使用することで、これを少し簡略化できreversed()
ます... では、外側は必要ありませんlist()
。
rotated = list(zip(*original))[::-1]
もちろん、リストを時計回りに3回回転させることもできます。:-)
zip
Python 3.xのリストにキャストする必要があることに注意してください!
これには3つの部分があります。
ただの観察です。入力はリストのリストですが、非常に優れたソリューションの回転: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]]
リストcompまたはマップはどちらも、内部タプルをリストに変換します。
def ruota_orario(matrix):
ruota=list(zip(*reversed(matrix)))
return[list(elemento) for elemento in ruota]
def ruota_antiorario(matrix):
ruota=list(zip(*reversed(matrix)))
return[list(elemento)[::-1] for elemento in ruota][::-1]
私自身もこの問題を抱えており、このテーマに関するすばらしいWikipediaページを見つけました(「一般的なローテーション」の段落: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 "=== === === === === === === === === "
反時計回りに回転(標準の列から行へのピボット)リストおよび辞書として
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]))
生成:
[['A', 'B', 'C', 'D'], [1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
[['A', 1, 1, 1, 1], ['B', 2, 2, 2], ['C', 3, 3], ['D', 4]]
{'A': [1, 1, 1, 1], 'B': [2, 2, 2], 'C': [3, 3], 'D': [4]}
zip(*original[::-1])
です。