Ce face Entry::or_default
or_default() este or_insert_with(Default::default), scris scurt. Valoarea implicită depinde de tipul valorilor: 0 pentru numere, false pentru bool, Vec::new(), String::new(), un HashMap gol etc. Tipul trebuie să implementeze Default.
Este forma cea mai scurtă pentru contoare (*m.entry(k).or_default() += 1) și pentru grupare (m.entry(k).or_default().push(x)). Funcționează la fel pe BTreeMap.
Ce returnează
&mut V.
Exemple
Exemplul 1: Contor de cuvinte, cu BTreeMap pentru ordine
BTreeMap are același entry; cheile ies sortate fără efort suplimentar.
use std::collections::BTreeMap;
fn main() {
let text = "mere pere mere prune pere mere caise";
let mut numar: BTreeMap<&str, u32> = BTreeMap::new();
for cuvant in text.split_whitespace() {
*numar.entry(cuvant).or_default() += 1;
}
println!("{:?}", numar);
}
Rezultat
{"caise": 1, "mere": 3, "pere": 2, "prune": 1}
Exemplul 2: Note grupate pe materii
use std::collections::HashMap;
fn main() {
let note = [("matematică", 9), ("română", 10), ("matematică", 7), ("fizică", 8), ("română", 9)];
let mut pe_materii: HashMap<&str, Vec<u32>> = HashMap::new();
for (materie, nota) in note {
pe_materii.entry(materie).or_default().push(nota);
}
let mut materii: Vec<_> = pe_materii.iter().collect();
materii.sort();
for (materie, lista) in materii {
let media = lista.iter().sum::<u32>() as f64 / lista.len() as f64;
println!("{materie:11} {:?} media {media:.2}", lista);
}
}
Rezultat
fizică [8] media 8.00
matematică [9, 7] media 8.00
română [10, 9] media 9.50
Exemplul 3: Dicționar în dicționar: vânzări pe oraș și produs
Primul or_default() creează dicționarul interior pentru oraș, al doilea creează contorul pentru produs.
use std::collections::BTreeMap;
fn main() {
let vanzari = [("Iași", "pâine", 3), ("Cluj", "lapte", 2), ("Iași", "lapte", 1), ("Iași", "pâine", 2)];
let mut tabel: BTreeMap<&str, BTreeMap<&str, u32>> = BTreeMap::new();
for (oras, produs, buc) in vanzari {
*tabel.entry(oras).or_default().entry(produs).or_default() += buc;
}
for (oras, produse) in &tabel {
println!("{oras}: {:?}", produse);
}
}
Rezultat
Cluj: {"lapte": 2}
Iași: {"lapte": 1, "pâine": 5}
Greșeli frecvente
- Valori de un tip fără
Default(de exemplu o structură proprie fără#[derive(Default)]): the trait bound `T: Default` is not satisfied. Adaugă derive-ul sau foloseșteor_insert_with. - Te aștepți la altă valoare inițială decât cea implicită (de exemplu 1). Pentru asta folosește
or_insert(1).
Comenzi înrudite
Entry::or_insert: Dacă cheia lipsește, inserează valoarea dată; în ambele cazuri returnează o referință mutabilă la valoarea din dicționar.Entry::or_insert_with: Ca or_insert, dar valoarea de inserat e calculată de un closure, apelat doar dacă cheia lipsește.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.BTreeMap: Dicționar cu cheile mereu sortate: aceleași operații ca HashMap, dar parcurgerea și afișarea sunt în ordinea cheilor.