Python에서 2 차원 배열 회전 라이너를 찾았습니다. rotated

프로그램에서 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해주길 바라며, 인덱스를 기반으로 반복 가능한 각 입력의 요소를 그룹화하거나, 즉 열을 그룹화합니다.


답변

영리한 부분입니다.

첫째, 주석에서 언급했듯이 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))))

“Martian smiley”슬라이스를 사용하여 간단히 단순화 할 수 있습니다 reversed(). 그러면 외부가 필요하지 않습니다 list().

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

물론 목록을 시계 방향으로 세 번 간단히 회전 할 수도 있습니다. 🙂


답변

여기에는 세 부분이 있습니다.

  1. original [::-1]은 원래 배열을 반대로합니다. 이 표기법은 Python 목록 슬라이싱입니다. 그러면 [start : end : step]에서 설명하는 원래 목록의 “하위 목록”이 제공됩니다. 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은 각각 길이가 m 인 n 개의 인수를 취하고 길이가 m 인 목록을 생성하는 함수입니다. 요소는 길이가 n이고 각 원본 목록의 해당 요소를 포함합니다. 예를 들어 zip ([1,2], [a, b], [x, y])은 [[1, a, x], [2, b, y]]입니다. Python 문서 도 참조하세요 .

답변

관찰 일뿐입니다. 입력은 목록 목록이지만 매우 멋진 솔루션의 출력은 rotated = 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은 모두 내부 튜플을 다시 목록으로 변환합니다.


답변

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 페이지를 찾았습니다 ( “Common rotations”단락에서 :
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]}