HashMap::get_mut în Rust

Returnează o referință mutabilă la valoarea unei chei, ca s-o modifici pe loc; None dacă cheia nu există.

Sintaxă
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
where K: Borrow<Q>, Q: Hash + Eq + ?Sized

Ce face HashMap::get_mut

get_mut(&cheie) dă Some(&mut valoare), prin care schimbi valoarea direct în dicționar (*v += 1, v.push(..)), fără s-o scoți și s-o pui la loc. Pentru o cheie lipsă returnează None și nu inserează nimic.

Dacă vrei „modifică dacă există, altfel inserează”, folosește entry(cheie). Pentru a modifica două valori deodată (de exemplu un transfer între două conturi) există get_disjoint_mut([a, b]) (Rust 1.86), pentru că două apeluri get_mut simultane nu sunt permise de regulile de împrumut.

Parametri

Parametru Descriere
k Referință la cheie.

Ce returnează

Option<&mut V>.

Exemple

Exemplul 1: Depunere în cont

use std::collections::HashMap;

fn main() {
    let mut conturi = HashMap::from([("Ana", 100), ("Mihai", 50)]);
    if let Some(sold) = conturi.get_mut("Ana") {
        *sold += 25;
    }
    match conturi.get_mut("Radu") {
        Some(sold) => *sold += 10,
        None => println!("Radu nu are cont"),
    }
    let mut lista: Vec<_> = conturi.iter().collect();
    lista.sort();
    println!("{:?}", lista);
}

Rezultat

Radu nu are cont
[("Ana", 125), ("Mihai", 50)]

Exemplul 2: Elevi repartizați pe grupe existente

Valorile sunt vectori; prin get_mut adăugăm în vectorul grupei. O grupă necunoscută nu este creată.

use std::collections::HashMap;

fn main() {
    let mut grupe: HashMap<&str, Vec<&str>> = HashMap::from([("A", vec![]), ("B", vec![])]);
    for (elev, grupa) in [("Ana", "A"), ("Mihai", "B"), ("Ioana", "A"), ("Radu", "C")] {
        match grupe.get_mut(grupa) {
            Some(lista) => lista.push(elev),
            None => println!("grupa {grupa} nu există, {elev} rămâne nerepartizat"),
        }
    }
    println!("A: {:?}", grupe["A"]);
    println!("B: {:?}", grupe["B"]);
}

Rezultat

grupa C nu există, Radu rămâne nerepartizat
A: ["Ana", "Ioana"]
B: ["Mihai"]

Exemplul 3: Transfer între două conturi

get_disjoint_mut returnează câte un Option<&mut V> pentru fiecare cheie (cheile trebuie să fie diferite).

use std::collections::HashMap;

fn main() {
    let mut conturi = HashMap::from([("Ana", 100), ("Mihai", 50)]);
    if let [Some(de_la), Some(catre)] = conturi.get_disjoint_mut(["Ana", "Mihai"]) {
        *de_la -= 30;
        *catre += 30;
    }
    println!("Ana: {}, Mihai: {}", conturi["Ana"], conturi["Mihai"]);
}

Rezultat

Ana: 70, Mihai: 80

Greșeli frecvente

  • Te aștepți ca get_mut să creeze cheia lipsă. Nu creează nimic; folosește entry(k).or_insert(..).
  • Ții două referințe get_mut în același timp: cannot borrow `m` as mutable more than once at a time. Fă modificările pe rând sau folosește get_disjoint_mut.
  • Uiți steluța: sold += 25 dă eroare de tip; sold este &mut i32, deci scrie *sold += 25.

Comenzi înrudite

  • HashMap::get: get caută o cheie și returnează Some(&valoare) sau None; contains_key spune doar dacă cheia există.
  • 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::and_modify: Dacă cheia există, aplică funcția dată pe valoarea ei; returnează Entry-ul, ca să poți continua cu or_insert.
  • HashMap::iter: Parcurge perechile din dicționar: iter dă (&cheie, &valoare), iter_mut dă (&cheie, &mut valoare). Ordinea e aleatorie.
  • Vec::get: Citește elementul de pe o poziție fără risc de panic: returnează Some(&element) sau None dacă poziția nu există.