Ordonarea unei colecții
Sortarea înseamnă aranjarea elementelor unei colecții într-o anumită ordine.
Unele tipuri au o ordine naturală. Numerele sunt ordonate după valoare: 1 vine înaintea lui 2. Șirurile sunt ordonate alfabetic: "four" vine înaintea lui "one". Pentru orice altceva, sau când vrei o altă ordine, dai o ordine personalizată cu o funcție cheie: o funcție care transformă un element în valoarea după care trebuie sortat.
Python sortează listele în două moduri:
sorted(s)returnează o listă nouă sortată și lasă originalul neschimbat. Funcționează pe orice iterabil.s.sort()sortează lista pe loc: ordinea inițială se pierde.
Ambele primesc aceleași două argumente cu nume: key= (funcția cheie) și reverse=True pentru ordine descrescătoare. Multe limbaje sortează cu o funcție de comparare care se uită la două elemente; Python cere în schimb o cheie pentru un singur element și compară cheile. Aproape orice funcție de comparare pe care ai scrie-o devine o funcție cheie mai scurtă, de exemplu key=len pentru a sorta după lungime.
Exemplele de mai jos folosesc cuvintele one, two, three, four.
Ordinea naturală
Ordinea naturală este ordinea pe care un tip o are de la sine: numerele după valoare, șirurile literă cu literă.
sorted(words) dă o listă nouă în ordine naturală. Pentru ordine descrescătoare nu sortezi de două ori: transmite reverse=True și lista nouă iese inversată.
Și tuplurile au o ordine naturală: Python le compară poziție cu poziție, iar prima diferență decide. Astfel, propriile tale date primesc o ordine fără efort. Un număr de versiune stocat ca tuplul (major, minor) este comparat întâi după major și doar când valorile major sunt egale decide minor — exact comparația reutilizabilă pe care altfel ai scrie-o de mână.
Copie sortată
sorted() creează o listă nouă, sortată alfabetic. Lista originală words este afișată după aceea pentru a arăta că nu s-a schimbat.
Ieșire: program Python complet
words = ["one", "two", "three", "four"]
# sorted() returnează o listă nouă sortată; words rămâne neschimbată
ordered = sorted(words)
print(ordered)
print(words)
Sortare descrescătoare
reverse=True face ca sorted() să returneze lista nouă în ordine descrescătoare, astfel încât cuvintele merg de la "two" până la "four".
Ieșire: program Python complet
words = ["one", "two", "three", "four"]
# reverse=True dă lista nouă în ordine descrescătoare
desc = sorted(words, reverse=True)
print(desc)
Un tip cu propria ordine
O versiune este tuplul (major, minor). Compararea tuplurilor se uită întâi la major; doar când valorile major sunt egale decide minor. (1, 2) > (1, 3) întreabă „este versiunea 1.2 mai mare decât 1.3?” și afișează False; (2, 0) > (1, 5) afișează True.
Ieșire: program Python complet
# O versiune este un tuplu (major, minor). Tuplurile se compară poziție cu
# poziție: major decide primul, minor doar departajează egalitatea.
v12 = (1, 2)
v13 = (1, 3)
v20 = (2, 0)
v15 = (1, 5)
# Este 1.2 mai mare decât 1.3?
print(v12 > v13)
# Este 2.0 mai mare decât 1.5?
print(v20 > v15)
Ordini personalizate
O ordine personalizată este orice ordine pe care o descrii cu o funcție cheie.
Transmite-o ca key=: Python apelează funcția o dată pentru fiecare element și sortează elementele după ce returnează ea. Sortarea din Python este stabilă: elementele cu chei egale își păstrează întotdeauna ordinea inițială. Nu ai nevoie niciodată de o sortare stabilă separată, de exemplu când sortezi cuvinte după lungime.
Sortarea după o singură proprietate a fiecărui element este cazul obișnuit: key=len sortează după lungime, iar o lambda extrage orice altceva, cum ar fi ultima literă a unui cuvânt.
Pentru ordine descrescătoare adaugă reverse=True. Acesta inversează compararea cheilor, iar elementele egale își păstrează în continuare ordinea inițială.
Pentru a sorta după un criteriu și apoi după altul, returnează un tuplu din funcția cheie. Tuplurile se compară poziție cu poziție, așa că a doua valoare departajează egalitatea atunci când prima spune că elementele sunt egale.
Sortare cu o funcție cheie
key=len dă fiecărui cuvânt lungimea sa drept cheie: 3 pentru "aaa", 2 pentru "bb", 1 pentru "c". Cheia cea mai mică vine prima, așa că cuvintele ajung ordonate de la cel mai scurt la cel mai lung. words.sort() face asta pe loc.
Ieșire: program Python complet
words = ["aaa", "bb", "c"]
# key=len sortează după lungimea fiecărui cuvânt: cuvintele mai scurte vin primele.
# sort() modifică lista pe loc.
words.sort(key=len)
print(words)
Sortare după lungime
Cuvintele sunt sortate cu key=len. "one" și "two" au amândouă 3 litere; sortarea stabilă păstrează "one" înaintea lui "two".
Ieșire: program Python complet
words = ["one", "two", "three", "four"]
# Sortarea este stabilă: cuvintele de lungime egală își păstrează ordinea inițială.
by_length = sorted(words, key=len)
print(by_length)
Sortare după ultima literă, descrescător
w[-1] este ultima literă a unui cuvânt. Cu reverse=True, cuvântul cu cea mai mare ultimă literă vine primul: "four" (r), apoi "two" (o), apoi cele două cuvinte care se termină în „e”, în ordinea lor inițială.
Ieșire: program Python complet
words = ["one", "two", "three", "four"]
# w[-1] este ultima literă; reverse=True inversează ordinea.
by_last = sorted(words, key=lambda w: w[-1], reverse=True)
print(by_last)
Sortare după lungime, apoi alfabetic
Cheia (len(w), w) este un tuplu: întâi lungimea. Când două cuvinte au aceeași lungime, a doua valoare — cuvântul însuși — le ordonează alfabetic.
Ieșire: program Python complet
words = ["aaa", "bb", "c", "b", "a", "aa", "ccc"]
# Cheia este un tuplu: întâi lungimea, apoi cuvântul însuși departajează egalitatea.
by_length_then_word = sorted(words, key=lambda w: (len(w), w))
print(by_length_then_word)
Verificarea ordinii sortate
Uneori vrei doar să afli dacă o listă este deja sortată, fără să o sortezi.
Python nu are o funcție is_sorted(), dar verificarea încape pe un rând: fiecare element trebuie să fie mai mic sau egal cu vecinul său din dreapta. zip(s, s[1:]) grupează fiecare element cu următorul, iar all() confirmă că fiecare pereche este în ordine. Pentru ordine descrescătoare, inversează comparația: a >= b în loc de a <= b.
Pentru a verifica ordinea unei singure proprietăți, cum ar fi vârsta unui utilizator, compară acea proprietate în interiorul verificării.
Verificare crescătoare și descrescătoare
all(a <= b ...) confirmă că 1, 2, 3, 4 sunt în ordine crescătoare. Comparația inversată a >= b confirmă că 4, 3, 2, 1 sunt în ordine descrescătoare.
Ieșire: program Python complet
ascending = [1, 2, 3, 4]
descending = [4, 3, 2, 1]
# zip(s, s[1:]) grupează fiecare element cu vecinul său din dreapta.
print(all(a <= b for a, b in zip(ascending, ascending[1:])))
# Comparația inversată verifică ordinea descrescătoare.
print(all(a >= b for a, b in zip(descending, descending[1:])))
Verificarea ordinii după un câmp
Utilizatorii sunt Alice (24), Bob (31) și Charlie (29). Verificarea se uită doar la vârste. Bob este mai în vârstă decât Charlie, așa că lista nu este sortată după vârstă, iar programul afișează False.
Ieșire: program Python complet
users = [("Alice", 24), ("Bob", 31), ("Charlie", 29)]
# Sunt utilizatorii în ordinea vârstei? Comparăm doar vârstele.
ages = [age for name, age in users]
print(all(a <= b for a, b in zip(ages, ages[1:])))
Ordinea inversă
Inversarea pune ultimul element primul și primul element ultimul.
Slice-ul words[::-1] construiește o copie inversată: originalul își păstrează ordinea. words.reverse(), în schimb, inversează lista pe loc. Există și funcția încorporată reversed(words): ea returnează un iterator care parcurge lista de la coadă la cap fără să construiască una nouă — învelește-l în list() când ai nevoie de o listă reală.
Copie inversată
Copia creată de words[::-1] este afișată, apoi este afișat originalul pentru a arăta că nu s-a schimbat.
Ieșire: program Python complet
words = ["one", "two", "three", "four"]
# words[::-1] construiește o copie inversată, deci originalul își păstrează ordinea.
backwards = words[::-1]
print(backwards)
print(words)
Ordinea aleatorie
Amestecarea pune elementele într-o ordine aleatorie.
Modulul random are o funcție shuffle(). La fel ca words.reverse(), lucrează pe loc, așa că amestecă o copie făcută cu words[:] dacă mai ai nevoie de original.
Un obiect random.Random(seed) cu un seed fix dă aceeași ordine „aleatorie” de fiecare dată când programul rulează cu acel seed. Acest lucru este util pentru teste și pentru exemple ca acesta. Funcția random.shuffle() de la nivelul modulului nu are un seed fix, așa că ordinea se schimbă la fiecare rulare.
Copie amestecată
Un obiect random.Random cu seed-ul 25 amestecă o copie a cuvintelor. Cu acest seed, rezultatul este ['two', 'three', 'one', 'four'] la fiecare rulare.
Ieșire: program Python complet
import random
words = ["one", "two", "three", "four"]
# Un seed fix dă aceeași ordine „aleatorie” la fiecare rulare.
rng = random.Random(25)
shuffled = words[:]
rng.shuffle(shuffled)
print(shuffled)