Python에서 2 차원 배열 회전
프로그램에서 2 차원 배열을 회전 할 필요가 있다고 작성했습니다. 최적의 솔루션을 찾다가이 작업을 수행하는 인상적인 원 라이너를 찾았습니다.
rotated = zip(*original[::-1])
지금 내 프로그램에서 사용하고 있으며 예상대로 작동합니다. 내 문제는 그것이 어떻게 작동하는지 이해하지 못한다는 것입니다.
누군가가 관련된 다른 기능이 원하는 결과를 얻는 방법을 설명 할 수 있다면 감사하겠습니다.
다음 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
해주길 바라며, 인덱스를 기반으로 반복 가능한 각 입력의 요소를 그룹화하거나, 즉 열을 그룹화합니다.
영리한 부분입니다. 분석은 다음과 같습니다.
[::-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)))
물론 목록을 시계 방향으로 세 번 간단히 회전 할 수도 있습니다. :-)
여기에는 세 부분이 있습니다.
- original [::-1]은 원래 배열을 반대로합니다. 이 표기법은 Python 목록 슬라이싱입니다. 이렇게하면 [start : end : step]에 설명 된 원래 목록의 "하위 목록"이 제공됩니다. start는 첫 번째 요소이고 end는 하위 목록에서 사용할 마지막 요소입니다. 단계는 모든 단계의 요소를 처음부터 끝까지 가져 간다고 말합니다. 생략 된 시작과 끝은 슬라이스가 전체 목록이됨을 의미하고 음수 단계는 요소를 반대로 가져옴을 의미합니다. 예를 들어 원본이 [x, y, z]이면 결과는 [z, y, x]가됩니다.
- 함수 호출의 인수 목록에서 목록 / 튜플 앞에있을 때 *는 목록 / 튜플을 "확장"하여 각 요소가 목록 / 튜플 자체가 아닌 함수에 대한 별도의 인수가됩니다. 따라서 args = [1,2,3]이면 zip (args)는 zip ([1,2,3])과 같지만 zip (* args)는 zip (1, 2,3).
- zip is a function that takes n arguments each of which is of length m and produces a list of length m, the elements of are of length n and contain the corresponding elements of each of the original lists. E.g., zip([1,2],[a,b],[x,y]) is [[1,a,x],[2,b,y]]. See also Python documentation.
Just an observation. The input is a list of lists, but the output from the very nice solution: rotated = zip(*original[::-1]) returns a list of tuples.
This may or may not be an issue.
It is, however, easily corrected:
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]]
The list comp or the map will both convert the interior tuples back to lists.
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]
I've had this problem myself and I've found the great wikipedia page on the subject (in "Common rotations" paragraph:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities
Then I wrote the following code, super verbose in order to have a clear understanding of what is going on.
I hope that you'll find it useful to dig more in the very beautiful and clever one-liner you've posted.
To quickly test it you can copy / paste it here:
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 "=== === === === === === === === === "
I was practicing python nested list comprehensions and coded the following to return a list of columns in a matrix, which is analogous to rotating the matrix:
def getColumns(matrix):
columns = [[row[col] for row in matrix] for col in range(len(matrix[1]))]
return columns
참고URL : https://stackoverflow.com/questions/8421337/rotating-a-two-dimensional-array-in-python
'Programing' 카테고리의 다른 글
sqlalchemy flush () 및 삽입 된 ID 가져 오기? (0) | 2020.08.20 |
---|---|
iOS 6 : 일부보기를 세로로 제한하고 다른보기는 회전하도록 허용하려면 어떻게합니까? (0) | 2020.08.20 |
ggplot2에서 "데이터 클래스 비정상"오류를 처리하는 방법은 무엇입니까? (0) | 2020.08.20 |
브라우저에서 채널을 열기위한 Slack URL (0) | 2020.08.20 |
java.util.Optional이 Serializable이 아닌 이유, 이러한 필드로 객체를 직렬화하는 방법 (0) | 2020.08.20 |