Ce face Vec::retain
retain primește un closure care se uită la fiecare element (prin referință) și răspunde cu true (păstrează) sau false (șterge). Elementele rămase își păstrează ordinea.
Este modul corect de a șterge mai multe elemente dintr-un vector după o condiție: trece o singură dată prin vector, fără problemele de indici pe care le ai cu remove într-o buclă.
Closure-ul este apelat exact o dată pe element, în ordine. Dacă vrei să și modifici elementele în timpul filtrării, folosește retain_mut (primește &mut T). Dacă ai nevoie de elementele scoase, filtrează cu iteratori (partition, extract_if).
Parametri
| Parametru | Descriere |
|---|---|
f |
Closure-ul care primește &T și returnează true pentru elementele care rămân. |
Ce returnează
Nimic; vectorul este modificat pe loc.
Exemple
Exemplul 1: Doar notele de trecere
|&n| desface referința primită, ca să lucrăm direct cu numărul.
fn main() {
let mut note = vec![4, 9, 3, 10, 7, 5, 2];
note.retain(|&n| n >= 5);
println!("note de trecere: {:?}", note);
}
Rezultat
note de trecere: [9, 10, 7, 5]
Exemplul 2: Produsele fără stoc ies din listă
Closure-ul primește o referință la tuplu; modelul (_, stoc) ignoră numele și ia stocul.
fn main() {
let mut produse = vec![("pâine", 0), ("lapte", 12), ("ouă", 30), ("unt", 0)];
let inainte = produse.len();
produse.retain(|(_, stoc)| *stoc > 0);
println!("eliminate {} produse fără stoc", inainte - produse.len());
for (nume, stoc) in &produse {
println!("{nume}: {stoc} buc.");
}
}
Rezultat
eliminate 2 produse fără stoc
lapte: 12 buc.
ouă: 30 buc.
Exemplul 3: retain_mut: modifică și filtrează dintr-o trecere
Fiecare abonament pierde o zi; cele ajunse la 0 zile ies din listă.
fn main() {
let mut abonamente = vec![("Ana", 3), ("Mihai", 1), ("Ioana", 2)];
for zi in 1..=3 {
abonamente.retain_mut(|(_, zile)| {
*zile -= 1;
*zile > 0
});
println!("după ziua {zi}: {:?}", abonamente);
}
}
Rezultat
după ziua 1: [("Ana", 2), ("Ioana", 1)]
după ziua 2: [("Ana", 1)]
după ziua 3: []
Greșeli frecvente
- Inversezi condiția:
retainpăstrează elementele pentru care closure-ul spunetrue, nu le șterge. - Încerci să modifici elementul în closure-ul lui
retain: primești&T, nu&mut T. Foloseșteretain_mut. - Ștergi cu
remove(i)într-o buclă pe indici. Indicii se decalează după fiecare ștergere;retainrezolvă problema dintr-o singură trecere.
Comenzi înrudite
Vec::dedup: Șterge elementele egale aflate unul după altul; dedup_by_key compară după o cheie calculată din fiecare element.Vec::drain: Scoate din vector elementele dintr-un interval de poziții și le dă înapoi ca iterator, mutate (fără copiere).Vec::swap_remove: Scoate elementul de pe o poziție și pune în locul lui ultimul element; este instantaneu, dar schimbă ordinea.Iterator::filter: Păstrează doar elementele pentru care condiția dată returnează true; restul sunt sărite.HashMap::retain: Păstrează doar perechile pentru care funcția dată returnează true; restul sunt șterse dintr-o singură trecere.