Iterator::zip în Rust

Parcurge două șiruri în paralel și produce perechi (a, b); se oprește când se termină cel mai scurt.

Sintaxă
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator

pub fn zip<A, B>(a: A, b: B) -> Zip<A::IntoIter, B::IntoIter>   // std::iter::zip, Rust 1.59

Ce face Iterator::zip

a.zip(b) produce perechi formate din câte un element din fiecare: (a1, b1), (a2, b2) etc. Al doilea argument poate fi orice parcurgibil (vector, tablou, interval, alt iterator). Când unul dintre ele se termină, se termină și zip; elementele rămase din celălalt sunt ignorate.

Funcția liberă std::iter::zip(a, b) face același lucru, dar se citește mai simetric: zip(&nume, &note). Pentru trei șiruri, înlănțuiește: a.zip(b).zip(c) produce ((x, y), z). Inversul lui zip este unzip. 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 de valori.

Ce returnează

Un iterator de perechi (element_a, element_b).

Exemple

Exemplul 1: Nume și note

fn main() {
    let nume = ["Ana", "Mihai", "Ioana"];
    let note = [9.5, 8.0, 10.0];
    for (n, nota) in nume.iter().zip(note.iter()) {
        println!("{n}: {nota:.2}");
    }
}

Rezultat

Ana: 9.50
Mihai: 8.00
Ioana: 10.00

Exemplul 2: std::iter::zip și oprirea la cel mai scurt

Sunt 4 zile, dar doar 3 temperaturi: joi nu apare.

use std::iter::zip;

fn main() {
    let zile = ["luni", "marți", "miercuri", "joi"];
    let temperaturi = [12, 15, 9];
    for (zi, t) in zip(zile, temperaturi) {
        println!("{zi}: {t}°C");
    }
    let perechi: Vec<(i32, char)> = zip(1.., ['a', 'b', 'c']).collect();
    println!("{:?}", perechi);
}

Rezultat

luni: 12°C
marți: 15°C
miercuri: 9°C
[(1, 'a'), (2, 'b'), (3, 'c')]

Exemplul 3: Total de plată și diferențe zi de zi

Al doilea calcul face zip între șir și același șir decalat cu o poziție (skip(1)).

fn main() {
    let preturi = [5.5, 8.0, 25.0];
    let cantitati = [4, 2, 1];
    let total: f64 = preturi.iter().zip(cantitati).map(|(p, c)| p * c as f64).sum();
    println!("total: {total:.2} lei");

    let vizitatori = [120, 135, 128, 160];
    let diferente: Vec<i32> = vizitatori.iter().zip(vizitatori.iter().skip(1)).map(|(a, b)| b - a).collect();
    println!("diferențe: {:?}", diferente);
}

Rezultat

total: 63.00 lei
diferențe: [15, -7, 32]

Greșeli frecvente

  • Te aștepți ca zip să semnaleze lungimi diferite. Se oprește în tăcere la cel mai scurt; verifică lungimile înainte dacă trebuie să fie egale.
  • Faci for i in 0..a.len() { a[i] ... b[i] }: dacă b e mai scurt, programul se oprește. zip este mai sigur.

Comenzi înrudite

  • Iterator::unzip: Desparte un iterator de perechi în două colecții: una cu primele elemente, alta cu al doilea element din fiecare pereche.
  • Iterator::enumerate: Adaugă fiecărui element poziția lui: produce perechi (index, element), cu indexul pornind de la 0.
  • Iterator::chain: Lipește două șiruri de valori: produce întâi toate elementele primului, apoi pe ale celui de-al doilea.
  • Vec::windows: windows dă ferestre suprapuse de câte n elemente consecutive; chunks împarte vectorul în bucăți separate de câte n.