Ce face Vec::sort_by
sort_by_key(|e| cheie) este varianta cea mai simplă: spui după ce să se sorteze (vârsta, prețul, lungimea numelui), iar elementele se ordonează crescător după acea cheie. Cheia trebuie să implementeze Ord.
sort_by(|a, b| ...) primește două elemente și returnează un Ordering (Less, Equal, Greater), de obicei obținut cu a.cmp(b). Inversând (b.cmp(a)) obții ordine descrescătoare. Pentru mai multe criterii, înlănțuiește cu .then_with(|| ...), iar pentru f64 folosește total_cmp.
Ambele sunt stabile: la chei egale, elementele își păstrează ordinea anterioară. Variantele sort_unstable_by și sort_unstable_by_key sunt mai rapide, fără această garanție. Cheia lui sort_by_key nu poate fi o referință în element; dacă e scump de calculat (de exemplu un String nou), sort_by_cached_key o calculează o singură dată pe element.
Parametri
| Parametru | Descriere |
|---|---|
compare |
La sort_by: closure care compară două elemente și returnează Ordering. |
f |
La sort_by_key: closure care calculează cheia de sortare a unui element. |
Ce returnează
Nimic; vectorul este sortat pe loc.
Exemple
Exemplul 1: Elevi după vârstă, apoi după medie
Mihai și Radu au aceeași medie (8,70). După a doua sortare, Radu rămâne înaintea lui Mihai, cum era după sortarea pe vârstă: sortarea este stabilă.
struct Elev {
nume: &'static str,
varsta: u32,
medie: f64,
}
fn afiseaza(titlu: &str, elevi: &[Elev]) {
println!("{titlu}:");
for e in elevi {
println!(" {:6} {} ani, media {:.2}", e.nume, e.varsta, e.medie);
}
}
fn main() {
let mut elevi = vec![
Elev { nume: "Ana", varsta: 17, medie: 9.45 },
Elev { nume: "Mihai", varsta: 16, medie: 8.70 },
Elev { nume: "Ioana", varsta: 17, medie: 9.80 },
Elev { nume: "Radu", varsta: 15, medie: 8.70 },
];
elevi.sort_by_key(|e| e.varsta);
afiseaza("după vârstă", &elevi);
elevi.sort_by(|a, b| b.medie.total_cmp(&a.medie));
afiseaza("după medie, descrescător", &elevi);
}
Rezultat
după vârstă:
Radu 15 ani, media 8.70
Mihai 16 ani, media 8.70
Ana 17 ani, media 9.45
Ioana 17 ani, media 9.80
după medie, descrescător:
Ioana 17 ani, media 9.80
Ana 17 ani, media 9.45
Radu 15 ani, media 8.70
Mihai 16 ani, media 8.70
Exemplul 2: Două criterii: preț descrescător, apoi nume
fn main() {
let mut produse = vec![("lapte", 8), ("cafea", 25), ("pâine", 5), ("unt", 12), ("ouă", 12), ("miere", 25)];
produse.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.cmp(b.0)));
for (nume, pret) in &produse {
println!("{pret:3} lei {nume}");
}
}
Rezultat
25 lei cafea
25 lei miere
12 lei ouă
12 lei unt
8 lei lapte
5 lei pâine
Exemplul 3: Sortare fără să conteze literele mari
Sortarea obișnuită pune literele mari înaintea celor mici. Cu cheia to_lowercase(), ordinea devine cea așteptată.
fn main() {
let mut nume = vec!["mihai", "Ana", "ioana", "Radu", "Bogdan"];
nume.sort();
println!("sort(): {:?}", nume);
nume.sort_by_key(|n| n.to_lowercase());
println!("sort_by_key(lowercase): {:?}", nume);
}
Rezultat
sort(): ["Ana", "Bogdan", "Radu", "ioana", "mihai"]
sort_by_key(lowercase): ["Ana", "Bogdan", "ioana", "mihai", "Radu"]
Greșeli frecvente
- Returnezi o referință din cheie:
v.sort_by_key(|e| &e.nume)dă o eroare de durată de viață (lifetime may not live long enough). Foloseștev.sort_by(|a, b| a.nume.cmp(&b.nume))sau clonează cheia. - Folosești
partial_cmp(..).unwrap()pentruf64: dacă apare unNaN, programul se oprește.total_cmpnu are această problemă. - Sortezi descrescător cu
sort()urmat dereverse()pe date cu chei egale: ordinea elementelor egale se inversează și ea.sort_by(|a, b| b.cmp(a))sausort_by_key(|x| Reverse(x))păstrează stabilitatea.
Comenzi înrudite
Vec::sort: Sortează vectorul crescător, pe loc. sort este stabilă (păstrează ordinea elementelor egale); sort_unstable e mai rapidă.Reverse: Învelitoare care inversează ordinea unei valori: transformă BinaryHeap în min-heap și sortează descrescător după cheie.Vec::binary_search: Caută rapid o valoare într-un vector sortat: Ok(poziție) dacă există, Err(poziție) unde ar trebui inserată.Iterator::min_by_key: Găsește elementul minim sau maxim după un criteriu: o cheie calculată (by_key) sau o funcție de comparare (by).Vec::reverse: Inversează pe loc ordinea elementelor: primul devine ultimul, ultimul devine primul.