To sprytne rozwiązanie.
Po pierwsze, jak zauważono w komentarzu, w Pythonie 3 zip()zwraca iterator, więc musisz załączyć całość, list()aby uzyskać rzeczywistą listę z powrotem, więc od 2020 r.
list(zip(*original[::-1]))
Oto podział:
[::-1]- sporządza płytką kopię oryginalnej listy w odwrotnej kolejności. Można również użyć, reversed()który utworzyłby odwrotny iterator po liście zamiast kopiowania listy (bardziej wydajna pamięć).
*- sprawia, że każda podlista w oryginalnej liście jest oddzielnym argumentem zip()(tzn. rozpakowuje listę)
zip()- pobiera jedną pozycję z każdego argumentu i tworzy z nich listę (cóż, krotkę) i powtarza, aż wszystkie podlisty zostaną wyczerpane. W tym miejscu faktycznie zachodzi transpozycja.
list()konwertuje wynik programu zip()na listę.
Zakładając, że masz to:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
Najpierw dostajesz to (płytka, odwrócona kopia):
[ [7, 8, 9],
[4, 5, 6],
[1, 2, 3] ]
Następnie każda z podlist jest przekazywana jako argument do zip:
zip([7, 8, 9], [4, 5, 6], [1, 2, 3])
zip() wielokrotnie zużywa jeden element od początku każdego ze swoich argumentów i tworzy z niego krotkę, aż nie będzie już żadnych elementów, w wyniku czego (po przekonwertowaniu na listę):
[(7, 4, 1),
(8, 5, 2),
(9, 6, 3)]
Bob jest twoim wujem.
Aby odpowiedzieć na pytanie @ IkeMiguel w komentarzu na temat obracania go w innym kierunku, jest to całkiem proste: wystarczy odwrócić zarówno sekwencje, które wchodzą, jak zipi wynik. Pierwszą można osiągnąć, usuwając, [::-1]a drugą, rzucając reversed()wokół całości. Ponieważ reversed()zwraca iterator na liście, będziemy musieli go list()obejść , aby ją przekonwertować. Z kilkoma dodatkowymi list()wywołaniami, aby przekonwertować iteratory na rzeczywistą listę. Więc:
rotated = list(reversed(list(zip(*original))))
Możemy to nieco uprościć, używając plastra „marsjańskiej buźki” zamiast reversed()… wtedy nie potrzebujemy zewnętrznego list():
rotated = list(zip(*original))[::-1]
Oczywiście możesz też po prostu trzykrotnie obrócić listę w prawo. :-)