Ce face Iterator::filter_map
filter_map(|x| ...) apelează closure-ul pe fiecare element. Dacă rezultatul este Some(y), produce y; dacă este None, sare peste element. Este echivalentul lui map urmat de filter(|o| o.is_some()) și map(|o| o.unwrap()), dar mai clar și fără unwrap.
Cazul clasic: transformarea textelor în numere cu s.parse().ok(), păstrând doar ce s-a putut converti. Ca toate adaptoarele, este leneș: nu face nimic până când iteratorul nu este consumat (de for, collect, sum, count etc.).
Parametri
| Parametru | Descriere |
|---|---|
f |
Closure-ul care returnează Some(valoare) pentru elementele păstrate și None pentru cele sărite. |
Ce returnează
Un iterator FilterMap cu valorile din Some.
Exemple
Exemplul 1: Doar textele care sunt numere
parse dă un Result; .ok() îl transformă în Option, așa că valorile greșite dispar.
fn main() {
let intrare = ["12", "abc", "7", "", "30", "4.5"];
let numere: Vec<u32> = intrare.iter().filter_map(|s| s.parse().ok()).collect();
println!("{:?}", numere);
println!("suma: {}", numere.iter().sum::<u32>());
}
Rezultat
[12, 7, 30]
suma: 49
Exemplul 2: Telefoanele celor care au completat câmpul
struct Contact {
nume: &'static str,
telefon: Option<&'static str>,
}
fn main() {
let agenda = vec![
Contact { nume: "Ana", telefon: Some("0722 111 222") },
Contact { nume: "Mihai", telefon: None },
Contact { nume: "Ioana", telefon: Some("0744 333 444") },
];
let de_sunat: Vec<String> = agenda
.iter()
.filter_map(|c| c.telefon.map(|t| format!("{}: {t}", c.nume)))
.collect();
println!("{:#?}", de_sunat);
}
Rezultat
[
"Ana: 0722 111 222",
"Ioana: 0744 333 444",
]
Exemplul 3: Valorile dintr-un fișier de configurare
Liniile fără = (comentarii, linii goale) dau None la split_once și sunt sărite.
fn main() {
let config = "# setări\nport=8080\n\nhost = localhost\ndebug=true";
let perechi: Vec<(&str, &str)> = config
.lines()
.filter_map(|linie| linie.split_once('='))
.map(|(k, v)| (k.trim(), v.trim()))
.collect();
println!("{:?}", perechi);
}
Rezultat
[("port", "8080"), ("host", "localhost"), ("debug", "true")]
Greșeli frecvente
- Scrii
.map(|s| s.parse::<u32>()).filter(|r| r.is_ok()).map(|r| r.unwrap()).filter_map(|s| s.parse().ok())face același lucru. - Folosești
filter_mapcând vrei să oprești totul la prima valoare greșită.filter_mapsare peste erori în tăcere; pentru oprire, colectează înResult<Vec<_>, _>.
Comenzi înrudite
Iterator::map: Transformă fiecare valoare a iteratorului cu o funcție și dă un iterator cu rezultatele; nu calculează nimic până la consumare.Iterator::filter: Păstrează doar elementele pentru care condiția dată returnează true; restul sunt sărite.Iterator::find_map: Aplică o funcție care returnează Option pe fiecare element și dă primul rezultat Some; se oprește acolo.Iterator::flat_map: flatten „turtește” un iterator de colecții într-un singur șir de valori; flat_map aplică întâi o funcție, apoi turtește.Iterator::map_while: Transformă elementele cât timp funcția returnează Some și se oprește la primul None.