W programie, który piszę, pojawiła się potrzeba obracania dwuwymiarowej tablicy. Szukając optymalnego rozwiązania znalazłem ten imponujący jednolinijkowy, który spełnia swoje zadanie:
rotated = zip(*original[::-1])
Używam go teraz w moim programie i działa zgodnie z oczekiwaniami. Mój problem polega jednak na tym, że nie rozumiem, jak to działa.
Byłbym wdzięczny, gdyby ktoś mógł wyjaśnić, w jaki sposób różne zaangażowane funkcje osiągają pożądany rezultat.
python
multidimensional-array
paldepind
źródło
źródło
Odpowiedzi:
Rozważ następującą dwuwymiarową listę:
Podzielmy to krok po kroku:
Ta lista jest przekazywana
zip()
przy użyciu funkcji rozpakowywania argumentów , więczip
wywołanie kończy się tym, że jest odpowiednikiem tego:Miejmy nadzieję, że komentarze wyjaśniają, co
zip
robi, zgrupuje elementy z każdego wejścia iterowalnego na podstawie indeksu, lub innymi słowy grupuje kolumny.źródło
rotated = [list(r) for r in zip(*original[::-1])]
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.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 argumentemzip()
(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 programuzip()
na listę.Zakładając, że masz to:
Najpierw dostajesz to (płytka, odwrócona kopia):
Następnie każda z podlist jest przekazywana jako argument do
zip
: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ę):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
zip
i wynik. Pierwszą można osiągnąć, usuwając,[::-1]
a drugą, rzucającreversed()
wokół całości. Ponieważreversed()
zwraca iterator na liście, będziemy musieli golist()
obejść , aby ją przekonwertować. Z kilkoma dodatkowymilist()
wywołaniami, aby przekonwertować iteratory na rzeczywistą listę. Więc:Możemy to nieco uprościć, używając plastra „marsjańskiej buźki” zamiast
reversed()
… wtedy nie potrzebujemy zewnętrznegolist()
:Oczywiście możesz też po prostu trzykrotnie obrócić listę w prawo. :-)
źródło
zip
w Pythonie 3.x musisz rzutować wynik na listę!Są na to trzy części:
źródło
Tylko obserwacja. Wejście to lista list, ale wynik bardzo fajnego rozwiązania: rotated = zip (* original [:: - 1]) zwraca listę krotek.
Może to stanowić problem, ale nie musi.
Można to jednak łatwo poprawić:
Kompozycja list lub mapa przekonwertują wewnętrzne krotki z powrotem na listy.
źródło
źródło
Sam miałem ten problem i znalazłem świetną stronę Wikipedii na ten temat (w akapicie „Wspólne rotacje”:
https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities
Następnie napisałem następujący kod, super gadatliwy, aby dobrze zrozumieć, co się dzieje.
Mam nadzieję, że okażą się przydatne, aby zagłębić się w tę bardzo piękną i sprytną linijkę, którą opublikowałeś.
Aby szybko to przetestować, możesz skopiować / wkleić tutaj:
http://www.codeskulptor.org/
źródło
Obracanie przeciwnie do ruchu wskazówek zegara (standardowa kolumna do wiersza) As List i Dict
Produkuje:
źródło
zip(*original[::-1])
działa.