Iterator::enumerate în Rust

Adaugă fiecărui element poziția lui: produce perechi (index, element), cu indexul pornind de la 0.

Sintaxă
fn enumerate(self) -> Enumerate<Self>   // produce (usize, Self::Item)

Ce face Iterator::enumerate

enumerate() transformă fiecare element x în perechea (i, x), unde i este un usize care începe de la 0 și crește cu 1. Este modul obișnuit de a avea și poziția, și valoarea într-o buclă: for (i, x) in v.iter().enumerate().

Pentru numerotare de la 1, scrie i + 1 la afișare. Indexul numără elementele care ajung la enumerate: pus după un filter, numără doar elementele filtrate. Ca toate adaptoarele, este leneș: nu face nimic până când iteratorul nu este consumat (de for, collect, sum, count etc.).

Ce returnează

Un iterator de perechi (usize, element).

Exemple

Exemplul 1: Listă numerotată

fn main() {
    let clasament = ["Ana", "Mihai", "Ioana"];
    for (i, nume) in clasament.iter().enumerate() {
        println!("{}. {nume}", i + 1);
    }
}

Rezultat

1. Ana
2. Mihai
3. Ioana

Exemplul 2: Pozițiile notelor sub 5

fn main() {
    let note = [8, 4, 9, 3, 10, 4];
    let pozitii: Vec<usize> = note
        .iter()
        .enumerate()
        .filter(|&(_, &n)| n < 5)
        .map(|(i, _)| i)
        .collect();
    println!("note sub 5 pe pozițiile {:?}", pozitii);
}

Rezultat

note sub 5 pe pozițiile [1, 3, 5]

Exemplul 3: Ordinea contează: enumerate înainte sau după filter

fn main() {
    let cuvinte = ["mere", "x", "pere", "y", "prune"];
    let inainte: Vec<(usize, &str)> = cuvinte.iter().copied().enumerate().filter(|(_, c)| c.len() > 1).collect();
    let dupa: Vec<(usize, &str)> = cuvinte.iter().copied().filter(|c| c.len() > 1).enumerate().collect();
    println!("enumerate apoi filter: {:?}", inainte);
    println!("filter apoi enumerate: {:?}", dupa);
}

Rezultat

enumerate apoi filter: [(0, "mere"), (2, "pere"), (4, "prune")]
filter apoi enumerate: [(0, "mere"), (1, "pere"), (2, "prune")]

Greșeli frecvente

  • Ții un contor separat (let mut i = 0; ... i += 1;) într-o buclă for. enumerate face asta fără risc de a uita incrementarea.
  • Uiți că indexul e usize: let x: i32 = i; nu compilează. Convertește cu i as i32.
  • Pui enumerate după filter și te aștepți la pozițiile originale. Pune-l înainte de filter.

Comenzi înrudite

  • Iterator::zip: Parcurge două șiruri în paralel și produce perechi (a, b); se oprește când se termină cel mai scurt.
  • Iterator::position: Returnează poziția (indexul de la 0) primului element care îndeplinește condiția, sau None.
  • Vec::iter: Cele trei moduri de a parcurge un vector: iter dă referințe, iter_mut dă referințe mutabile, into_iter dă elementele.
  • Iterator::take: take(n) produce cel mult primele n elemente; skip(n) sare peste primele n și produce restul.