Essa é uma parte inteligente.
Primeiro, conforme observado em um comentário, em Python 3 zip()
retorna um iterador, então você precisa incluir tudo list()
para obter uma lista real de volta, então a partir de 2020 é realmente:
list(zip(*original[::-1]))
Aqui está o detalhamento:
[::-1]
- faz uma cópia superficial da lista original na ordem inversa. Também poderia usar o reversed()
que produziria um iterador reverso sobre a lista em vez de realmente copiar a lista (mais eficiente em termos de memória).
*
- torna cada sublista na lista original um argumento separado para zip()
(ou seja, descompacta a lista)
zip()
- pega um item de cada argumento e faz uma lista (bem, uma tupla) a partir deles, e repete até que todas as sublistas sejam esgotadas. É aqui que a transposição realmente acontece.
list()
converte a saída de zip()
em uma lista.
Então, supondo que você tenha isso:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
Primeiro você obtém isto (cópia superficial e invertida):
[ [7, 8, 9],
[4, 5, 6],
[1, 2, 3] ]
Em seguida, cada uma das sublistas é passada como um argumento para zip
:
zip([7, 8, 9], [4, 5, 6], [1, 2, 3])
zip()
consome repetidamente um item do início de cada um de seus argumentos e faz uma tupla a partir dele, até que não haja mais itens, resultando em (após ser convertido em uma lista):
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
E Bob é seu tio.
Para responder à pergunta de @IkeMiguel em um comentário sobre girá-lo na outra direção, é bastante simples: você só precisa inverter as sequências que entram zip
e o resultado. O primeiro pode ser alcançado removendo o [::-1]
e o segundo pode ser alcançado jogando um em reversed()
volta de tudo. Uma vez que reversed()
retorna um iterador sobre a lista, precisaremos list()
contorná- lo para convertê-lo. Com algumas list()
chamadas extras para converter os iteradores em uma lista real. Assim:
rotated = list(reversed(list(zip(*original))))
Podemos simplificar isso um pouco usando a fatia "smiley marciano" em vez de reversed()
... então não precisamos do exterior list()
:
rotated = list(zip(*original))[::-1]
Claro, você também pode simplesmente girar a lista no sentido horário três vezes. :-)