Ce face Iterator::filter
filter(|x| condiție) produce doar elementele care îndeplinesc condiția, în ordinea inițială. Elementele nu sunt modificate. Ca toate adaptoarele, este leneș: nu face nimic până când iteratorul nu este consumat (de for, collect, sum, count etc.).
Closure-ul primește o referință la element (&Self::Item), ca să poată doar să se uite la el. Pentru v.iter(), elementul este deja &T, deci closure-ul primește &&T. De aici modelele des întâlnite: |&&x| x > 5 sau |x| **x > 5. Cu .copied() înainte, lucrezi cu &T simplu.
Parametri
| Parametru | Descriere |
|---|---|
predicate |
Closure-ul care primește &element și returnează true pentru elementele păstrate. |
Ce returnează
Un iterator Filter cu elementele care trec condiția.
Exemple
Exemplul 1: Note de trecere și orașe lungi
fn main() {
let note = vec![4, 9, 3, 10, 7, 5];
let trecere: Vec<&i32> = note.iter().filter(|&&n| n >= 5).collect();
println!("{:?}", trecere);
let peste_8: Vec<i32> = note.iter().copied().filter(|n| *n > 8).collect();
println!("{:?}", peste_8);
let orase = ["Iași", "Constanța", "Arad", "Timișoara"];
let lungi: Vec<&str> = orase.into_iter().filter(|o| o.chars().count() > 5).collect();
println!("{:?}", lungi);
}
Rezultat
[9, 10, 7, 5]
[9, 10]
["Constanța", "Timișoara"]
Exemplul 2: Mai multe filtre înlănțuite
Fiecare filter lucrează doar pe ce a trecut de cel dinainte; totul se face dintr-o singură parcurgere.
struct Comanda {
oras: &'static str,
suma: u32,
platita: bool,
}
fn main() {
let comenzi = vec![
Comanda { oras: "Iași", suma: 120, platita: true },
Comanda { oras: "Cluj", suma: 300, platita: false },
Comanda { oras: "Iași", suma: 45, platita: true },
Comanda { oras: "Iași", suma: 210, platita: true },
];
let mari_platite_iasi: Vec<u32> = comenzi
.iter()
.filter(|c| c.oras == "Iași")
.filter(|c| c.platita)
.filter(|c| c.suma >= 100)
.map(|c| c.suma)
.collect();
println!("{:?}", mari_platite_iasi);
}
Rezultat
[120, 210]
Greșeli frecvente
- Compari direct
|x| x > 5pev.iter(): expected `&&{integer}`, found integer. Desfă referințele:|&&x| x > 5, sau|x| **x > 5, sau pune.copied()înainte. - Folosești
filterurmat decount()doar pentru a verifica dacă există un element:anyse oprește la primul găsit. - Vrei să ștergi elemente dintr-un vector existent:
filtercreează un iterator nou. Pe loc, foloseșteVec::retain.
Comenzi înrudite
Iterator::filter_map: Transformă și filtrează într-un singur pas: păstrează valorile din Some(..) returnate de funcție și sare peste None.Iterator::map: Transformă fiecare valoare a iteratorului cu o funcție și dă un iterator cu rezultatele; nu calculează nimic până la consumare.Vec::retain: Păstrează în vector doar elementele pentru care funcția dată returnează true; restul sunt șterse, în aceeași ordine.Iterator::partition: Împarte elementele în două colecții: cele pentru care condiția e adevărată și cele pentru care e falsă.Iterator::take_while: take_while dă elemente cât timp condiția e adevărată și se oprește la primul care nu o îndeplinește; skip_while sare până atunci.