Python에서 2차원 배열 회전
제가 쓰고 있는 프로그램에서 2차원 배열을 회전시켜야 할 필요성이 제기되었습니다.최적의 솔루션을 찾다가 이 작업을 수행하는 인상적인 단일 라이너를 발견했습니다.
rotated = zip(*original[::-1])
지금 프로그램에서 사용하고 있는데 예상대로 작동합니다.하지만 제 문제는 그것이 어떻게 작동하는지 이해할 수 없다는 것입니다.
관련된 다양한 기능들이 어떻게 원하는 결과를 얻을 수 있는지 누군가 설명해주시면 감사하겠습니다.
그것은 영리한 부분입니다.
한 것처럼 에서, 에에언것, Python 3에서.zip()를 복기를반전에포합야니함으로 .list()실제 목록을 다시 가져오려면 2020년 기준으로 다음과 같습니다.
list(zip(*original[::-1]))
내역은 다음과 같습니다.
[::-1]원래 목록의 복사본을 역순으로 만듭니다.사용할 수도 있습니다.reversed()이는 목록을 실제로 복사하는 것보다 목록 위에 역방향 반복기를 생성합니다(메모리 효율성이 더 높음).*각을 원본 목록 목을에 대별인 만듭로다니수도에 대한 .zip()(즉, 목록포풉니다을장의)zip()각 인수에서 하나의 항목을 가져와 해당 항목에서 목록(태플)을 만들고 모든 하위 목록이 소진될 때까지 반복합니다.이것이 바로 전치가 실제로 일어나는 곳입니다.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()각 인수의 시작부터 하나의 항목을 반복적으로 사용하여 더 이상 항목이 없을 때까지 튜플을 만듭니다(목록으로 변환된 후).
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
밥은 네 삼촌이고
시키는 것에 대한 . @IkeMiguel에 두 뒤집으면 .zip그리고 그 결과.첫 번째는 다음을 제거함으로써 달성할 수 있습니다.[::-1]그리고 두 번째는 던짐으로써 달성될 수 있습니다.reversed()전체적으로부터reversed()합니다. 이 에는 목록위반반환합다니를기를 넣어야 . 우리는 입력해야 합니다.list()그것을 변환하기 위해 그 주변에.몇 개의 여분으로.list()반복자를 실제 목록으로 변환하는 호출입니다.그래서:
rotated = list(reversed(list(zip(*original))))
는 우는 " 션마스일마리를사스그수있용다여습니단조순할것금"가 아닌 " 더 할 수 .reversed()그러면 우리는 외부가 필요하지 않습니다.list():
rotated = list(zip(*original))[::-1]
물론 목록을 시계 방향으로 세 번만 돌리면 됩니다. :-)
다음의 2차원 목록을 고려해 보십시오.
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인덱스를 기준으로 각 입력 테이블의 요소를 그룹화하거나, 즉 열을 그룹화합니다.
여기에는 세 부분이 있습니다.
- original[::-1]은(는) 원래 배열을 반대로 만듭니다.이 표기법은 파이썬 목록 슬라이싱입니다.이렇게 하면 [start:end:step]에 설명된 원래 목록의 "하위 목록"이 제공됩니다. 시작은 첫 번째 요소이고 끝은 하위 목록에서 사용할 마지막 요소입니다.step은 모든 단계의 요소를 첫 번째부터 마지막까지 취하라고 말합니다.시작과 끝을 생략하면 조각이 전체 목록이 되고, 음의 단계는 요소가 반대로 표시된다는 것을 의미합니다.예를 들어, 원본이 [x,y,z]이면 결과는 [z,y,x]가 됩니다.
- 함수 호출의 인수 목록에서 리스트/튜플 앞에 *가 있는 경우는 리스트/튜플의 각 요소가 리스트/튜플 자체가 아닌 함수에 대한 개별 인수가 되도록 리스트/튜플을 "확장"하는 것을 의미합니다.예를 들어, args = [1,2,3]이면 zip(args)은 zip([1,2,3])과 동일하지만 zip(args)은 zip(1,2,3)과 동일합니다.
- zip은 각각 길이가 m인 인수를 취하고 길이가 m인 목록을 생성하며 요소는 길이가 n이고 각 원래 목록의 해당 요소를 포함하는 함수입니다.예를 들어 zip([1,2], [a,b], [x,y])은 [1,a,x], [2,b,y]입니다.Python 설명서도 참조하십시오.
그냥 관찰일 뿐입니다.입력은 목록 목록이지만 매우 좋은 솔루션인 회전 = 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]]
리스트 컴퍼레이션 또는 맵은 둘 다 내부 튜플을 리스트로 다시 변환합니다.
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]
저 자신도 이 문제를 겪었고 그 주제에 대한 훌륭한 위키백과 페이지를 발견했습니다("공통 회전" 단락:
https://en.wikipedia.org/wiki/Rotation_matrix#://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]}
매트릭스 시계 방향 회전:
mat = [[1,2,3],[4,5,6],[7,8,9]]
clock_rotated_mat = list(zip(*mat[::-1]))
# [(7, 4, 1), (8, 5, 2), (9, 6, 3)]
[::-1] - 행렬의 역행렬
zip(_) - 인덱스에 따라 각 목록의 중첩된 목록 값을 압축 해제합니다.
list() - 목록 개체로 다시 캐스트합니다.
마찬가지로 행렬 반시계방향 회전:
mat = [[1,2,3],[4,5,6],[7,8,9]]
anti_clock_rotated_mat = list(zip(*mat))[::-1]
# [(3, 6, 9), (2, 5, 8), (1, 4, 7)]
보다 단순한 하나의 라이너는 다음과 같습니다.
new_matrix = [list(row) for row in zip(*matrix)]
또는
new_matrix = list()
for row in zip(*matrix):
new_matrix.append(list(row))
주요 부분은 각 반복 시 함수 인수로 전달되는 반복 가능 변수에서 하나의 요소가 있는 반복 가능 개체를 반환하는 zip 내장 함수를 사용하는 것입니다.리스트 a와 b를 넘겨 zip을 하고 던지기를 반복합니다.
a = [1, 2, 3]
b = [4, 5, 6]
for t in zip(a, b):
print(t) # Print (1, 4) at the 1-st iteration, (2, 5) - 2nd,
# and (3, 6) at the end.
또 다른 부분은 요소를 수동으로 전달하는 대신 언팩 작업(*)을 사용하는 것입니다.위의 변수를 목록으로 포장한 다음 zip 기능으로 압축을 풀 수 있습니다.
a = [1, 2, 3]
b = [4, 5, 6]
pack = [a, b]
for t in zip(*pack):
print(t)
포장 풀기에 대한 자세한 내용은 문서를 참조하십시오.
언급URL : https://stackoverflow.com/questions/8421337/rotating-a-two-dimensional-array-in-python
'programing' 카테고리의 다른 글
| application.dev.properties 파일을 로드하지 않는 Springboot (0) | 2023.07.15 |
|---|---|
| 발송 시 특성이 작업(vuex)에 나타나지 않는 이유는 무엇입니까? (0) | 2023.07.15 |
| 장고에서 동적 필드 룩업으로 쿼리 세트를 어떻게 필터링합니까? (0) | 2023.07.15 |
| Node.js - 여러 비동기 호출 대기 (0) | 2023.07.15 |
| '구독' 속성이 'void' 유형에 없습니다.Angular 2 asp.net 코어 (0) | 2023.07.15 |