Ce face Entry::and_modify
and_modify(|v| ...) rulează closure-ul doar pentru o cheie existentă (Occupied); pentru o cheie lipsă nu face nimic. Returnează tot un Entry, deci se înlănțuiește de obicei cu or_insert: m.entry(k).and_modify(|n| *n += 1).or_insert(1).
Forma aceasta e utilă când valoarea inițială diferă de modificare: la prima apariție pui ceva, la următoarele actualizezi altfel (de exemplu minim și maxim, prima și ultima dată). Pentru un simplu contor, *m.entry(k).or_insert(0) += 1 e la fel de bun.
Parametri
| Parametru | Descriere |
|---|---|
f |
Closure care primește &mut V și modifică valoarea. |
Ce returnează
Același Entry, pentru înlănțuire.
Exemple
Exemplul 1: Contor cu and_modify + or_insert
use std::collections::HashMap;
fn main() {
let mut voturi: HashMap<&str, u32> = HashMap::new();
for v in ["Ana", "Mihai", "Ana", "Ioana", "Ana", "Mihai"] {
voturi.entry(v).and_modify(|n| *n += 1).or_insert(1);
}
let mut rezultat: Vec<_> = voturi.into_iter().collect();
rezultat.sort_by(|a, b| b.1.cmp(&a.1));
println!("{:?}", rezultat);
}
Rezultat
[("Ana", 3), ("Mihai", 2), ("Ioana", 1)]
Exemplul 2: Prețul minim și maxim al fiecărui produs
La prima apariție inserăm (preț, preț); la următoarele actualizăm capetele intervalului.
use std::collections::HashMap;
fn main() {
let citiri = [("lapte", 8.5), ("pâine", 5.0), ("lapte", 7.9), ("lapte", 9.2), ("pâine", 5.5)];
let mut interval: HashMap<&str, (f64, f64)> = HashMap::new();
for (produs, pret) in citiri {
interval
.entry(produs)
.and_modify(|(min, max)| {
*min = min.min(pret);
*max = max.max(pret);
})
.or_insert((pret, pret));
}
let mut lista: Vec<_> = interval.into_iter().collect();
lista.sort_by(|a, b| a.0.cmp(b.0));
for (produs, (min, max)) in lista {
println!("{produs}: între {min:.2} și {max:.2} lei");
}
}
Rezultat
lapte: între 7.90 și 9.20 lei
pâine: între 5.00 și 5.50 lei
Exemplul 3: Modificare fără inserare
Fără or_insert, o cheie lipsă rămâne lipsă: „pere” nu apare în dicționar.
use std::collections::HashMap;
fn main() {
let mut stoc = HashMap::from([("mere", 10)]);
stoc.entry("mere").and_modify(|n| *n -= 3);
stoc.entry("pere").and_modify(|n| *n -= 3);
println!("{:?}", stoc);
}
Rezultat
{"mere": 7}
Greșeli frecvente
- Scrii
and_modifydupăor_insert:or_insertreturnează&mut V, nuEntry, deci nu se poate înlănțui. Ordinea corectă: întâiand_modify, apoior_insert. - Te aștepți ca
and_modifysă ruleze și pentru valoarea tocmai inserată deor_insert. Nu rulează: o cheie nouă primește exact valoarea dinor_insert.
Comenzi înrudite
HashMap::entry: Caută o cheie o singură dată și îți dă „locul” ei (Entry), ca să inserezi, să citești sau să modifici fără o a doua căutare.Entry::or_insert: Dacă cheia lipsește, inserează valoarea dată; în ambele cazuri returnează o referință mutabilă la valoarea din dicționar.HashMap::get_mut: Returnează o referință mutabilă la valoarea unei chei, ca s-o modifici pe loc; None dacă cheia nu există.Entry::or_default: Dacă cheia lipsește, inserează valoarea implicită a tipului (0, vector gol, text gol) și returnează &mut V.