186 votes

Rotation d'un tableau bidimensionnel en Python

Dans un programme que j'écris, la nécessité de faire pivoter un tableau à deux dimensions est apparue. En cherchant la solution optimale, j'ai trouvé cette impressionnante ligne simple qui fait l'affaire :

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

Je l'utilise actuellement dans mon programme et il fonctionne comme prévu. Mon problème, cependant, est que je ne comprends pas comment il fonctionne.

J'apprécierais que quelqu'un puisse expliquer comment les différentes fonctions impliquées permettent d'atteindre le résultat souhaité.

10 votes

En effet. Je l'ai trouvé dans ce Une question.

1voto

Pitto Points 160

J'ai eu ce problème moi-même et j'ai trouvé l'excellente page wikipedia sur le sujet (dans le paragraphe "rotations communes" :
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities

J'ai ensuite écrit le code suivant, super verbeux afin de bien comprendre ce qui se passe.

J'espère que vous trouverez utile de creuser davantage dans le très beau et très intelligent one-liner que vous avez posté.

Pour le tester rapidement, vous pouvez le copier/coller ici :
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 "=== === === === === === === === === "

0voto

Paul Kenjora Points 226

Rotation dans le sens inverse des aiguilles d'une montre (pivot standard de la colonne à la ligne) comme liste et dictée

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]))

Produit :

[['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]}

0voto

Rotation de la matrice dans le sens des aiguilles d'une montre :

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] - inverse la matrice

zip(*_) - dépaquette les valeurs des listes imbriquées de chaque liste en fonction de son index.

list() - retourne à l'objet liste.

de même, rotation de la matrice dans le sens inverse des aiguilles d'une montre :

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)]

0voto

Je m'exerçais à comprendre les listes imbriquées en python et j'ai codé ce qui suit pour retourner une liste de colonnes dans une matrice, ce qui est analogue à la rotation de la matrice :

def getColumns(matrix):
  columns = [[row[col] for row in matrix] for col in range(len(matrix[1]))]
  return columns

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X