HashMap::iter în Rust

Parcurge perechile din dicționar: iter dă (&cheie, &valoare), iter_mut dă (&cheie, &mut valoare). Ordinea e aleatorie.

Sintaxă
pub fn iter(&self) -> Iter<'_, K, V>          // produce (&K, &V)
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> // produce (&K, &mut V)

Ce face HashMap::iter

iter() produce tupluri (&K, &V). Bucla for (k, v) in &m face același lucru. iter_mut() (sau for (k, v) in &mut m) produce (&K, &mut V), deci poți modifica valorile, dar nu și cheile.

Ordinea perechilor nu este garantată și se schimbă de la o rulare la alta. Pentru rezultate stabile, colectează perechile într-un vector și sortează-l (v.sort() sortează după cheie, apoi după valoare), sau folosește un BTreeMap.

for (k, v) in m (fără &) consumă dicționarul și dă perechile prin valoare.

Ce returnează

Un iterator de perechi.

Exemple

Exemplul 1: Bonus la note, apoi afișare ordonată

Colectăm perechile (&&str, &i32) și le sortăm; tuplurile se sortează după primul câmp, numele.

use std::collections::HashMap;

fn main() {
    let mut note = HashMap::from([("Ana", 9), ("Mihai", 7), ("Ioana", 10)]);
    for (_, nota) in note.iter_mut() {
        *nota = (*nota + 1).min(10);
    }
    let mut perechi: Vec<_> = note.iter().collect();
    perechi.sort();
    for (nume, nota) in perechi {
        println!("{nume}: {nota}");
    }
}

Rezultat

Ana: 10
Ioana: 10
Mihai: 8

Exemplul 2: Clasament: sortare după valoare

Sortăm descrescător după puncte; la egalitate, după nume, ca rezultatul să fie mereu același.

use std::collections::HashMap;

fn main() {
    let puncte = HashMap::from([("Ana", 42), ("Mihai", 57), ("Ioana", 42), ("Radu", 61)]);
    let mut clasament: Vec<(&str, u32)> = puncte.iter().map(|(&n, &p)| (n, p)).collect();
    clasament.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(b.0)));
    for (loc, (nume, p)) in clasament.iter().enumerate() {
        println!("{}. {nume} - {p} puncte", loc + 1);
    }
}

Rezultat

1. Radu - 61 puncte
2. Mihai - 57 puncte
3. Ana - 42 puncte
4. Ioana - 42 puncte

Exemplul 3: Parcurgere directă: ordinea se schimbă

Numărul de perechi și suma sunt mereu aceleași; ordinea liniilor nu.

use std::collections::HashMap;

fn main() {
    let orase = HashMap::from([("Iași", 271), ("Cluj", 286), ("Timișoara", 250), ("Constanța", 263)]);
    let mut total = 0;
    for (oras, mii) in &orase {
        println!("{oras}: {mii} mii de locuitori");
        total += mii;
    }
    println!("total: {total} mii");
}

Rezultat posibil (ordinea diferă la fiecare rulare)

Cluj: 286 mii de locuitori
Timișoara: 250 mii de locuitori
Iași: 271 mii de locuitori
Constanța: 263 mii de locuitori
total: 1070 mii

Greșeli frecvente

  • Scrii teste sau rezultate care depind de ordinea lui iter(). Merge o dată și pică la rularea următoare. Sortează.
  • Încerci să inserezi sau să ștergi în timp ce parcurgi: cannot borrow as mutable. Colectează cheile întâi sau folosește retain.

Comenzi înrudite

  • HashMap::keys: keys parcurge doar cheile, values doar valorile, iar values_mut dă valorile ca referințe mutabile, pentru modificare.
  • HashMap::retain: Păstrează doar perechile pentru care funcția dată returnează true; restul sunt șterse dintr-o singură trecere.
  • BTreeMap: Dicționar cu cheile mereu sortate: aceleași operații ca HashMap, dar parcurgerea și afișarea sunt în ordinea cheilor.
  • Iterator::collect: Consumă iteratorul și adună valorile într-o colecție: Vec, String, HashMap, HashSet, chiar Result sau Option.
  • Vec::sort_by: Sortează după o regulă proprie: sort_by primește o funcție de comparare, sort_by_key o cheie calculată din element.