Iterator::chain în Rust

Lipește două șiruri de valori: produce întâi toate elementele primului, apoi pe ale celui de-al doilea.

Sintaxă
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
where U: IntoIterator<Item = Self::Item>

Ce face Iterator::chain

a.chain(b) parcurge a până la capăt și continuă cu b. Ambele trebuie să producă același tip de element. Nu se creează niciun vector intermediar: e ideal când vrei să tratezi două colecții ca una singură, doar pentru o parcurgere.

Pentru a adăuga un singur element la început sau la sfârșit, combină cu std::iter::once(x). Ca toate adaptoarele, este leneș: nu face nimic până când iteratorul nu este consumat (de for, collect, sum, count etc.).

Parametri

Parametru Descriere
other Al doilea șir, cu același tip de element.

Ce returnează

Un iterator Chain.

Exemple

Exemplul 1: Două liste parcurse ca una

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

Rezultat

1. Ana
2. Mihai
3. Ioana
4. Radu

Exemplul 2: Antet, rânduri și total, cu once

use std::iter::once;

fn main() {
    let produse = [("pâine", 5), ("lapte", 8)];
    let total: u32 = produse.iter().map(|(_, p)| p).sum();
    let linii: Vec<String> = once(String::from("produs,pret"))
        .chain(produse.iter().map(|(n, p)| format!("{n},{p}")))
        .chain(once(format!("TOTAL,{total}")))
        .collect();
    println!("{}", linii.join("\n"));
}

Rezultat

produs,pret
pâine,5
lapte,8
TOTAL,13

Exemplul 3: Intervale lipite

fn main() {
    let ore_lucru: Vec<u32> = (9..12).chain(13..17).collect();
    println!("{:?}", ore_lucru);
    let suma: u32 = (1..=3).chain(10..=12).sum();
    println!("{suma}");
}

Rezultat

[9, 10, 11, 13, 14, 15, 16]
39

Greșeli frecvente

  • Lipești șiruri cu tipuri diferite de element: v.iter().chain(w.into_iter()) dă type mismatch (&T față de T). Folosește aceeași formă pentru ambele (iter() și iter()).
  • Creezi un vector nou doar ca să parcurgi două colecții ([a.clone(), b.clone()].concat()). chain nu copiază nimic.

Comenzi înrudite

  • iter::once: once(x) creează un iterator cu un singur element; empty() creează un iterator fără niciun element.
  • Iterator::zip: Parcurge două șiruri în paralel și produce perechi (a, b); se oprește când se termină cel mai scurt.
  • Iterator::flat_map: flatten „turtește” un iterator de colecții într-un singur șir de valori; flat_map aplică întâi o funcție, apoi turtește.
  • Vec::extend_from_slice: extend_from_slice adaugă copii ale elementelor dintr-un slice; append mută toate elementele altui vector și îl golește.