HashMap::extend în Rust

Adaugă în dicționar toate perechile dintr-un iterator (vector, alt dicționar); cheile existente primesc valoarea nouă.

Sintaxă
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T)
// și, pentru K și V de tip Copy:
fn extend<T: IntoIterator<Item = (&K, &V)>>(&mut self, iter: T)

Ce face HashMap::extend

extend vine din trait-ul Extend: primește orice se poate parcurge și produce perechi (cheie, valoare), de exemplu un Vec de tupluri sau alt HashMap. Fiecare pereche este inserată ca prin insert, deci la o cheie care există deja, valoarea nouă o înlocuiește pe cea veche.

Pentru chei și valori de tip Copy (numere, &str), poți da și perechi de referințe: a.extend(&b) copiază perechile din b fără să-l consume. Dacă vrei să aduni valorile pentru cheile comune, nu să le înlocuiești, parcurge perechile și folosește entry.

Parametri

Parametru Descriere
iter Sursa perechilor: Vec<(K, V)>, un tablou de tupluri, alt dicționar, un iterator.

Ce returnează

Nimic.

Exemple

Exemplul 1: Prețuri noi peste cele vechi

„lapte” exista deja; după extend are prețul nou.

use std::collections::HashMap;

fn main() {
    let mut preturi = HashMap::from([("pâine", 5), ("lapte", 8)]);
    let noi = vec![("cafea", 25), ("lapte", 9)];
    preturi.extend(noi);

    let mut lista: Vec<_> = preturi.into_iter().collect();
    lista.sort();
    println!("{:?}", lista);
}

Rezultat

[("cafea", 25), ("lapte", 9), ("pâine", 5)]

Exemplul 2: Unire de dicționare: înlocuire față de adunare

extend(&filiala) înlocuiește valoarea pentru Iași (120 devine 30). Dacă vrem totalul vânzărilor, adunăm cu entry.

use std::collections::HashMap;

fn sortat<'a>(m: &HashMap<&'a str, u32>) -> Vec<(&'a str, u32)> {
    let mut v: Vec<_> = m.iter().map(|(&k, &val)| (k, val)).collect();
    v.sort();
    v
}

fn main() {
    let centrala = HashMap::from([("Iași", 120), ("București", 300)]);
    let filiala = HashMap::from([("Cluj", 80), ("Iași", 30)]);

    let mut inlocuit = centrala.clone();
    inlocuit.extend(&filiala);
    println!("extend:  {:?}", sortat(&inlocuit));

    let mut adunat = centrala.clone();
    for (&oras, &suma) in &filiala {
        *adunat.entry(oras).or_insert(0) += suma;
    }
    println!("adunare: {:?}", sortat(&adunat));
}

Rezultat

extend:  [("București", 300), ("Cluj", 80), ("Iași", 30)]
adunare: [("București", 300), ("Cluj", 80), ("Iași", 150)]

Greșeli frecvente

  • Folosești extend ca să unești contoare: valorile se înlocuiesc, nu se adună. Folosește entry(k).or_insert(0) += v într-o buclă.
  • Dai &alt când valorile sunt String: varianta cu referințe merge doar pentru tipuri Copy. Dă alt (consumat) sau alt.clone().

Comenzi înrudite

  • HashMap::insert: Pune o pereche cheie-valoare în dicționar; dacă cheia exista, înlocuiește valoarea și o returnează pe cea veche.
  • 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.
  • Vec::extend_from_slice: extend_from_slice adaugă copii ale elementelor dintr-un slice; append mută toate elementele altui vector și îl golește.
  • Iterator::collect: Consumă iteratorul și adună valorile într-o colecție: Vec, String, HashMap, HashSet, chiar Result sau Option.