Zabawy z sortowaniem
Raz na jakiś czas przydałoby się nam coś posortować. Jak wiadomo rodzajów sortowania jest wiele jednak nie o tym będzie ten wpis. My skupimy się raczej na dobrym wykorzystaniu tego co Python nam daje. Jest spora szansa, że mechanizmy wbudowane w język załatwią 80% twoich problemów. Moim zdaniem najlepiej uczyć się poprzez serię prostych i krótkich przykładów. Zatem do boju.
Sortowanie listy
Podaną listę lista1 = [4, 3, 6, 7, 3, 0, 9, 3, 6]
posortuj w kolejności od największej do najmniejszej.
lista1 = [4, 3, 6, 7, 3, 0, 9, 3, 6] lista1.sort(reverse=True) print(lista1)
Skorzystaliśmy tu z metody ”sort” wbudowanej w listę. Dodatkowo ustawiliśmy flagę ”reverse” na ”True”, która implikuje kierunek sortowania. Domyślnie ”reverse” ustawione jest na ”False” co powoduje sortowanie od najmniejszej do największej. Warto pamiętać, że użycie metody ”sort” powoduje zmianę naszej oryginalnej listy.
Sortowanie krotki
Pewnie korciło by Cię by postąpić podobnie jak z listą. Niestety tak się nie da. Krotki (tuple) nie mają metody ”sort”. To dlatego, że jak wcześniej wspominaliśmy metoda ta powoduje zamianę oryginalnej kolekcji jaką poddajemy sortowaniu. Jak pewnie wiesz nie mamy takiej mocy by dokonać zmian na tupli bo jest ona niezmienna (immutable) – tak została zaprojektowana. Z pomocą przychodzi nam funkcja ”sorted”.
lista1 = (4, 3, 6, 7, 3, 0, 9, 3, 6) #lista1.sort(reverse=True)tak sie nie da lista1 = tuple(sorted(lista1)) print(lista1)
Output:
(0, 3, 3, 3, 4, 6, 6, 7, 9)
Jak widać funkcja ”sorted” nie modyfikuje sortowanej kolekcji. Zamiast tego zwraca już posortowaną kolekcję w postaci listy. No właśnie, aby być zgodnym z zadaniem przerobiliśmy naszą listę na tuplę. Oczywiście ty nie zawsze musisz postępować w ten sposób.
Sortowanie słownika
Sortowanie po kluczach
slownik = {7 : 'siedem', 1 : 'jeden', 4 : 'cztery'} print(sorted(slownik)) # tak ale to robi liste posortowanych indeksow
Output:
[1, 4, 7]
Chyba nie do końca oczekiwaliśmy takiego efektu. To co udało się osiągnąć to lista posortowanych kluczy, która pewnie nie jest zbyt użyteczna. Spróbujmy zatem innego podejścia.
Sortowanie po kluczach ale pamiętając o wartościach
slownik = {7 : 'siedem', 1 : 'jeden', 4 : 'cztery'} wynik = [] for key, value in sorted(slownik.items()): wynik.append((key, value)) print(wynik)
Output:
[(1, 'jeden'), (4, 'cztery'), (7, 'siedem')]
Tym razem sortowaniu nie poddaliśmy jedynie kluczy. Skorzystaliśmy z metody ”items” tak aby jednocześnie sortować klucze wraz z wartościami. Następnie przeiterowaliśmy się po naszej wynikowej liście by zapisać wyniki jako lista tupli klucz-wartość.
Sortowanie po wartościach
slownik = {7 : 'siedem', 1 : 'jeden', 4 : 'cztery'} wynik = [] for key, value in sorted(slownik.items(), key=lambda x: x[1]): wynik.append((key, value)) print(wynik)
Output:
[(4, 'cztery'), (1, 'jeden'), (7, 'siedem')]
Zauważ jak niewiele zmian było potrzebne by zacząć sortować po wartościach. Skorzystaliśmy z drugiego parametru funkcji ”sorted” o nazwie ”key”. Parametr ten może przyjąć dowolną funkcję. Działa to tak, że każdy element z naszej kolekcji jest poddawany działaniu funkcji i dopiero jej wynik służy jako wartość do sortowania. W naszym przypadku ze wszystkich elementów będących krotkami klucz-wartość my skupiamy się tylko na drugim elemencie krotki, czyli wartości. Oczywiście funkcja ”sorted” dalej zwraca cała zawartość naszej oryginalnej kolekcji tyle, że posortowaną. Funkcja przekazana jako ”key” służy tylko do tymczasowego generowania wartości które będą sortowane by w odpowiednim miejscu ulokować dany element.
Czemu sortowanie słownika nie zwraca słownika
Do tej porty poddając sortowaniu kolekcję typu słownik (dict) jako wynik dostawaliśmy posortowaną listę. Oczywiście lista ta zawierała klucze i wartości z naszego słownika, jednak nie był to posortowany słownik, a raczej posortowana lista. Zastanawiałeś się pewnie czemu nie da się posortować słownika tak samo jak robiliśmy to z listą. W przypadku listy wywoływaliśmy metodę sort i w magiczny sposób za chwile dysponowaliśmy już posortowaną kolekcją. Wcześniej mówiliśmy, że z tuplą te czary nie zadziałają bo tupla jest kolekcją niezmienną. Jednak słownik tak jak i listę możemy modyfikować. O co więc tu chodzi. Aby to zrozumieć trzeba troszkę dokładniej spojrzeć na nasz słownik. Otóż nasz słownik (dict) tak naprawdę powinien nosić nazwę słownik nieposortowany (unordered dict). Zatem nie posortowanie naszej kolekcji wynika po prostu ze specyfiki samego słownika. Poniekąd dzięki nie posortowaniu nasz słownik tak szybko może odwoływać się po kluczach do swoich elementów. Zatem moja propozycja jest taka:
from collections import OrderedDict slownik = {7 : 'siedem', 1 : 'jeden', 4 : 'cztery'} nowy_slownik = OrderedDict(sorted(slownik.items(), key=lambda x: x[1])) print(nowy_slownik) print(nowy_slownik[1])
Output:
OrderedDict([(4, 'cztery'), (1, 'jeden'), (7, 'siedem')]) jeden
Prawda, że ładne ? Skorzystaliśmy z innej kolekcji ”OrderedDict”, by to w niej trzymać już posortowane po wartościach dane z naszego słownika. Jak widzisz dzięki temu dalej możemy się do nich odwoływać poprzez indeksy.