C'est très malin.
Premièrement, comme indiqué dans un commentaire, dans Python 3 zip()
renvoie un itérateur, il faut donc enfermer le tout dans list()
pour obtenir une liste réelle, donc à partir de 2020, c'est en fait.. :
list(zip(*original[::-1]))
Voici le détail :
-
[::-1]
- fait une copie superficielle de la liste originale dans l'ordre inverse. On peut aussi utiliser reversed()
qui produirait un itérateur inversé sur la liste plutôt que de copier réellement la liste (plus efficace en mémoire).
-
*
- fait de chaque sous-liste de la liste originale un argument séparé pour zip()
(c'est-à-dire qu'il dépile la liste)
-
zip()
- prend un élément de chaque argument et en fait une liste (enfin, un tuple), et répète jusqu'à ce que toutes les sous-listes soient épuisées. C'est ici que la transposition se produit réellement.
-
list()
convertit la sortie de zip()
à une liste.
Donc, en supposant que vous avez ceci :
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
Vous obtenez d'abord ceci (copie inversée et peu profonde) :
[ [7, 8, 9],
[4, 5, 6],
[1, 2, 3] ]
Ensuite, chacune des sous-listes est passée en argument à zip
:
zip([7, 8, 9], [4, 5, 6], [1, 2, 3])
zip()
consomme de manière répétée un élément du début de chacun de ses arguments et en fait un tuple, jusqu'à ce qu'il n'y ait plus d'éléments, ce qui donne (après conversion en liste) :
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
Et Bob est ton oncle.
Pour répondre à la question de @IkeMiguel dans un commentaire concernant la rotation dans l'autre sens, c'est assez simple : il suffit d'inverser les deux séquences qui vont dans zip
et le résultat. Le premier peut être obtenu en supprimant le [::-1]
et la seconde peut être réalisée en lançant un reversed()
autour de tout ça. Depuis reversed()
renvoie un itérateur sur la liste, nous devrons mettre la fonction list()
autour de que pour le convertir. Avec un peu plus de list()
pour convertir les itérateurs en une liste réelle. Donc :
rotated = list(reversed(list(zip(*original))))
Nous pouvons simplifier un peu cela en utilisant la tranche "smiley martien" plutôt que reversed()
... alors nous n'avons pas besoin de l'extérieur. list()
:
rotated = list(zip(*original))[::-1]
Bien sûr, vous pouvez aussi simplement faire tourner la liste trois fois dans le sens des aiguilles d'une montre :-)
10 votes
En effet. Je l'ai trouvé dans ce Une question.