Ce face Iterator::fold
fold(init, |acc, x| ...) începe cu acumulatorul acc = init, apoi, pentru fiecare element, calculează noul acumulator din cel vechi și din element. Rezultatul final este ultimul acumulator. Pentru un iterator gol, rezultatul este chiar init.
sum, product, count, max sunt cazuri particulare de fold. Folosește fold când rezultatul are alt tip decât elementele (un text, un tuplu cu mai multe totaluri, o structură) sau când nu există o metodă gata făcută. Este un consumator: parcurge iteratorul (sau doar cât are nevoie) și pornește lanțul de adaptoare leneșe din fața lui.
Parametri
| Parametru | Descriere |
|---|---|
init |
Valoarea inițială a acumulatorului (și rezultatul pentru un iterator gol). |
f |
Closure care primește acumulatorul și elementul curent și returnează noul acumulator. |
Ce returnează
Acumulatorul final, de tipul B.
Exemple
Exemplul 1: Suma, produsul și un text construit
fn main() {
let numere = [3, 5, 2, 4];
let suma = numere.iter().fold(0, |acc, x| acc + x);
let produs = numere.iter().fold(1, |acc, x| acc * x);
println!("suma = {suma}, produs = {produs}");
let text = numere.iter().fold(String::new(), |mut acc, x| {
if !acc.is_empty() {
acc.push_str(" + ");
}
acc.push_str(&x.to_string());
acc
});
println!("{text} = {suma}");
}
Rezultat
suma = 14, produs = 120
3 + 5 + 2 + 4 = 14
Exemplul 2: Minim, maxim și medie dintr-o singură trecere
Acumulatorul este un tuplu (minim, maxim, sumă). Funcționează și pentru f64, unde min()/max() de pe iterator nu există.
fn main() {
let temperaturi = [12.5, -3.0, 7.25, 18.0, 4.5];
let (min, max, suma) = temperaturi
.iter()
.fold((f64::INFINITY, f64::NEG_INFINITY, 0.0), |(mn, mx, s), &t| (mn.min(t), mx.max(t), s + t));
println!("minim {min}, maxim {max}, medie {:.2}", suma / temperaturi.len() as f64);
}
Rezultat
minim -3, maxim 18, medie 7.85
Exemplul 3: Iterator gol: rezultatul este valoarea inițială
fn main() {
let goale: Vec<u32> = Vec::new();
let total = goale.iter().fold(100, |acc, x| acc + x);
println!("{total}");
}
Rezultat
100
Greșeli frecvente
- Folosești
foldpentru o sumă simplă:sum()e mai clar. - Valoarea inițială are alt tip decât vrei:
fold(0, |acc, x| acc + x)pef64dă eroare (0e întreg). Scriefold(0.0, ...). - Construiești un
Stringcuacc + &x.to_string()la fiecare pas și apoi te miri că e lent: fiecare+poate realoca. E în regulă pentru liste mici; pentru multe elemente,collect::<Vec<_>>().join(..).
Comenzi înrudite
Iterator::reduce: Combină elementele două câte două, folosind primul element ca valoare inițială; returnează None pentru un iterator gol.Iterator::try_fold: Ca fold, dar funcția returnează Option sau Result și oprirea are loc la primul None sau Err.Iterator::sum: sum adună toate elementele, product le înmulțește; tipul rezultatului trebuie precizat.Iterator::scan: Ca fold, dar produce câte un rezultat după fiecare element: o stare actualizată pas cu pas, de exemplu un total cumulat.