HashMap::insert în Rust

Pune o pereche cheie-valoare în dicționar; dacă cheia exista, înlocuiește valoarea și o returnează pe cea veche.

Sintaxă
pub fn insert(&mut self, k: K, v: V) -> Option<V>

Ce face HashMap::insert

insert(cheie, valoare) adaugă perechea. Dacă cheia nu exista, returnează None. Dacă exista, valoarea veche este înlocuită și returnată în Some(veche); cheia rămâne cea inițială.

Atât cheia, cât și valoarea sunt mutate în dicționar. După m.insert(nume, adresa) cu două String-uri, variabilele nume și adresa nu mai pot fi folosite. Pentru tipuri Copy (numere, &str) se face o copie.

Dacă vrei să inserezi doar când cheia lipsește, sau să actualizezi o valoare existentă (de exemplu un contor), folosește entry: face căutarea o singură dată.

Parametri

Parametru Descriere
k Cheia.
v Valoarea asociată cheii.

Ce returnează

None dacă cheia era nouă, altfel Some(valoarea veche).

Exemple

Exemplul 1: Valoarea veche este returnată

use std::collections::HashMap;

fn main() {
    let mut stoc = HashMap::new();
    println!("{:?}", stoc.insert("mere", 50));
    println!("{:?}", stoc.insert("pere", 20));
    println!("{:?}", stoc.insert("mere", 35));
    println!("mere: {}, pere: {}", stoc["mere"], stoc["pere"]);
}

Rezultat

None
None
Some(50)
mere: 35, pere: 20

Exemplul 2: Cheile String sunt mutate în dicționar

Căutarea se poate face cu &str, fără să creezi un String nou.

use std::collections::HashMap;

fn main() {
    let mut email: HashMap<String, String> = HashMap::new();
    let nume = String::from("Ana");
    let adresa = String::from("ana@exemplu.ro");
    email.insert(nume, adresa);
    // nume și adresa au fost mutate; de acum doar dicționarul le deține

    email.insert(String::from("Mihai"), String::from("mihai@exemplu.ro"));
    println!("{:?}", email.get("Ana"));
    println!("{} adrese", email.len());
}

Rezultat

Some("ana@exemplu.ro")
2 adrese

Exemplul 3: Ultimul oraș al fiecărei persoane

La o cheie repetată, insert returnează orașul vechi, deci putem anunța mutarea.

use std::collections::HashMap;

fn main() {
    let adrese = [("Ana", "Iași"), ("Mihai", "Cluj"), ("Ana", "Brașov"), ("Mihai", "Cluj")];
    let mut ultimul_oras = HashMap::new();
    for (nume, oras) in adrese {
        if let Some(vechi) = ultimul_oras.insert(nume, oras) {
            if vechi != oras {
                println!("{nume} s-a mutat din {vechi} în {oras}");
            }
        }
    }
    let mut lista: Vec<_> = ultimul_oras.into_iter().collect();
    lista.sort();
    println!("{:?}", lista);
}

Rezultat

Ana s-a mutat din Iași în Brașov
[("Ana", "Brașov"), ("Mihai", "Cluj")]

Greșeli frecvente

  • Folosești o variabilă String după ce ai pus-o în dicționar: borrow of moved value. Pune o copie (nume.clone()) sau citește valoarea din dicționar.
  • Scrii if !m.contains_key(&k) { m.insert(k, v); }: două căutări. m.entry(k).or_insert(v) face același lucru cu una.
  • Ignori valoarea returnată și pierzi, fără să vrei, o valoare veche. Dacă suprascrierea nu e intenționată, verifică rezultatul lui insert sau folosește entry.

Comenzi înrudite

  • HashMap: Dicționarul din Rust: asociază fiecărei chei o valoare și o găsește foarte repede după cheie. Ordinea nu este garantată.
  • 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::or_insert: Dacă cheia lipsește, inserează valoarea dată; în ambele cazuri returnează o referință mutabilă la valoarea din dicționar.
  • HashMap::extend: Adaugă în dicționar toate perechile dintr-un iterator (vector, alt dicționar); cheile existente primesc valoarea nouă.