Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Iterator::enumerate() / zip() / flat_map()

Iterator::enumerate() / zip() / flat_map()

Since: Rust 1.0(2015)

Rust iterators include enumerate() for indexed iteration, zip() for combining two iterators, and flat_map() for transforming and flattening nested iterators.

Syntax

for (i, val) in vec!["a", "b", "c"].iter().enumerate() {
    println!("{}: {}", i, val);
}

// zip(): combines two iterators into an iterator of tuples.
let keys = vec!["a", "b", "c"];
let vals = vec![1, 2, 3];
let pairs: Vec<(_, _)> = keys.iter().zip(vals.iter()).collect();

// flat_map(): transform and flatten the results.
let words = vec!["user_a user_c", "user_e user_b"];
let chars: Vec<&str> = words.iter().flat_map(|s| s.split_whitespace()).collect();

// flatten(): flatten a nested iterator by one level.
let nested = vec![vec![1, 2], vec![3, 4], vec![5]];
let flat: Vec<i32> = nested.into_iter().flatten().collect();

Method Reference

MethodDescription
iter.enumerate()Returns an iterator of (index, value) tuples.
iter.zip(other)Combines two iterators into an iterator of (a, b) tuples.
iter.flat_map(|x| ...)Flattens the result when the mapping closure returns an iterator.
iter.flatten()Flattens a nested iterator by one level.
iter.chain(other)Concatenates two iterators into a single iterator.
iter.take(n)Takes only the first n elements.
iter.skip(n)Skips the first n elements.
iter.step_by(n)Takes every nth element.
iter.rev()Returns a reversed iterator (requires DoubleEndedIterator).
iter.peekable()Returns an iterator that lets you peek at the next element without consuming it.

Sample Code

sample_iter_enumerate_zip_flatmap.rs
fn main() {
    // enumerate(): loop with index.
    let pilots = vec!["user_a", "user_c", "user_e"];
    for (i, pilot) in pilots.iter().enumerate() {
        println!("{}: {}", i, pilot);
    }

    // enumerate() to build a numbered list.
    let numbered: Vec<String> = pilots.iter()
        .enumerate()
        .map(|(i, p)| format!("{}. {}", i + 1, p))
        .collect();
    println!("numbered: {:?}", numbered);

    // zip(): combine two Vecs.
    let names = vec!["user_a", "user_c", "user_e"];
    let scores = vec![85, 90, 92];
    let combined: Vec<(_, _)> = names.iter().zip(scores.iter()).collect();
    println!("zip: {:?}", combined);

    // zip() to pair names with BGM tracks.
    let bgms = vec!["track_x", "track_y", "track_z"];
    let name_bgm: Vec<(_, _)> = names.iter().zip(bgms.iter()).collect();
    println!("name-bgm: {:?}", name_bgm);

    // zip() to build a HashMap.
    use std::collections::HashMap;
    let map: HashMap<_, _> = names.iter().zip(scores.iter()).collect();
    println!("zip to HashMap: {:?}", map);

    // flat_map(): split each string into words and flatten.
    let sentences = vec!["user_a user_c user_e", "user_b user_d"];
    let words: Vec<&str> = sentences.iter().flat_map(|s| s.split_whitespace()).collect();
    println!("flat_map words: {:?}", words);

    // flatten(): flatten nested Vecs.
    let nested = vec![vec![1, 2, 3], vec![4, 5], vec![6]];
    let flat: Vec<i32> = nested.into_iter().flatten().collect();
    println!("flatten: {:?}", flat);

    // chain(): concatenate two iterators.
    let a = vec![1, 2, 3];
    let b = vec![4, 5, 6];
    let chained: Vec<i32> = a.iter().chain(b.iter()).copied().collect();
    println!("chain: {:?}", chained);

    // take() and skip().
    let v: Vec<i32> = (1..=10).collect();
    let first3: Vec<_> = v.iter().take(3).collect();
    let skip3: Vec<_> = v.iter().skip(3).collect();
    println!("take(3): {:?}", first3);
    println!("skip(3): {:?}", skip3);
}

Compile with the following command:

rustc iter_enumerate_zip_flatmap.rs
./iter_enumerate_zip_flatmap
0: user_a
1: user_c
2: user_e
numbered: ["1. user_a", "2. user_c", "3. user_e"]
zip: [("user_a", 85), ("user_c", 90), ("user_e", 92)]
name-bgm: [("user_a", "track_x"), ("user_c", "track_y"), ("user_e", "track_z")]
zip to HashMap: {"user_a": 85, "user_c": 90, "user_e": 92}
flat_map words: ["user_a", "user_c", "user_e", "user_b", "user_d"]
flatten: [1, 2, 3, 4, 5, 6]
chain: [1, 2, 3, 4, 5, 6]
take(3): [1, 2, 3]
skip(3): [4, 5, 6, 7, 8, 9, 10]

Common Mistakes

Common mistake 1: zip() silently truncates at the shorter iterator

zip() stops as soon as the shorter of the two iterators is exhausted. Elements from the longer iterator are silently dropped.

fn main() {
    let names = vec!["user_a", "user_b", "user_c", "user_d"]; // 4 elements
    let scores = vec![90, 85, 75]; // 3 elements

    let pairs: Vec<_> = names.iter().zip(scores.iter()).collect();
    println!("{:?}", pairs);
    // [("user_a", 90), ("user_b", 85), ("user_c", 75)]
    // "user_d" is silently dropped

    println!("original: {}, zipped: {}", names.len(), pairs.len());
    // original: 4, zipped: 3
}

Common mistake 2: using map() when flat_map() is needed

map() wraps the closure's return value as-is. flat_map() flattens one level of nesting. Use flat_map() when the closure returns an iterator or collection.

fn main() {
    let sentences = vec!["user_a user_b", "user_c user_d"];

    // map() produces Vec<Vec<&str>> — nested
    let nested: Vec<Vec<&str>> = sentences.iter()
        .map(|s| s.split_whitespace().collect())
        .collect();
    println!("{:?}", nested); // [["user_a", "user_b"], ["user_c", "user_d"]]

    // flat_map() produces Vec<&str> — flattened
    let flat: Vec<&str> = sentences.iter()
        .flat_map(|s| s.split_whitespace())
        .collect();
    println!("{:?}", flat); // ["user_a", "user_b", "user_c", "user_d"]
}

Overview

zip() stops when the shorter iterator is exhausted, so it handles iterators of different lengths safely. If you need all elements from both sides, use zip_longest() from the itertools crate.

flat_map() is equivalent to map().flatten(). It is also handy for processing nested Options or Results — for example, iter.flat_map(|x| x.ok()) extracts only the successful values, ignoring errors.

For transforming and filtering, see Iterator::map() / filter().

If you find any errors or copyright issues, please .