Ce face Entry::or_insert
m.entry(k).or_insert(v) înseamnă: „dacă k nu există, pune v; apoi dă-mi valoarea lui k”. Rezultatul este &mut V, prin care poți modifica imediat valoarea: *m.entry(k).or_insert(0) += 1 numără aparițiile.
Dacă cheia există, valoarea dată este ignorată, iar valoarea existentă rămâne. Atenție: argumentul este calculat oricum, chiar dacă nu e folosit (ca orice argument de funcție). Pentru valori scumpe de construit, folosește or_insert_with, care primește un closure apelat doar la nevoie.
Parametri
| Parametru | Descriere |
|---|---|
default |
Valoarea inserată dacă cheia lipsește. |
Ce returnează
&mut V: referință mutabilă la valoarea din dicționar (cea existentă sau cea tocmai inserată).
Exemple
Exemplul 1: Literele unui cuvânt
Afișăm sortat după literă. „ă” vine după literele fără diacritice, pentru că are un cod Unicode mai mare.
use std::collections::HashMap;
fn main() {
let mut litere: HashMap<char, usize> = HashMap::new();
for c in "mămăligă".chars() {
*litere.entry(c).or_insert(0) += 1;
}
let mut lista: Vec<_> = litere.into_iter().collect();
lista.sort();
println!("{:?}", lista);
}
Rezultat
[('g', 1), ('i', 1), ('l', 1), ('m', 2), ('ă', 3)]
Exemplul 2: Vânzări totale pe oraș
use std::collections::HashMap;
fn main() {
let vanzari = [("Iași", 120.5), ("Cluj", 80.0), ("Iași", 30.25), ("București", 200.0), ("Cluj", 19.5)];
let mut total: HashMap<&str, f64> = HashMap::new();
for (oras, suma) in vanzari {
*total.entry(oras).or_insert(0.0) += suma;
}
let mut orase: Vec<_> = total.keys().copied().collect();
orase.sort();
for o in orase {
println!("{o:10} {:8.2} lei", total[o]);
}
}
Rezultat
București 200.00 lei
Cluj 99.50 lei
Iași 150.75 lei
Exemplul 3: Referința primită se folosește de mai multe ori
Ținem referința într-o variabilă, o modificăm de două ori și abia apoi citim din nou dicționarul.
use std::collections::HashMap;
fn main() {
let mut scoruri = HashMap::from([("Mihai", 30)]);
let scor = scoruri.entry("Ana").or_insert(0);
*scor += 10;
*scor *= 2;
println!("Ana: {scor}");
let scor = scoruri.entry("Mihai").or_insert(0);
*scor += 5;
println!("Mihai: {scor} (avea deja 30, iar 0 a fost ignorat)");
}
Rezultat
Ana: 20
Mihai: 35 (avea deja 30, iar 0 a fost ignorat)
Greșeli frecvente
- Uiți steluța:
m.entry(k).or_insert(0) += 1dă binary assignment operation `+=` cannot be applied to type `&mut {integer}`. Scrie*m.entry(k).or_insert(0) += 1. - Dai ca valoare implicită ceva scump (
Vec::with_capacity(1000), un calcul): se execută la fiecare apel, chiar dacă cheia există. Foloseșteor_insert_with. - Te aștepți ca
or_insert(v)să suprascrie valoarea existentă. Nu o atinge; pentru suprascriere foloseșteinsert.
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_with: Ca or_insert, dar valoarea de inserat e calculată de un closure, apelat doar dacă cheia lipsește.Entry::or_default: Dacă cheia lipsește, inserează valoarea implicită a tipului (0, vector gol, text gol) și returnează &mut V.Entry::and_modify: Dacă cheia există, aplică funcția dată pe valoarea ei; returnează Entry-ul, ca să poți continua cu or_insert.