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::map() / filter()

Iterator::map() / filter()

Since: Rust 1.0(2015)

Rust iterators provide map() for transforming elements and filter() for selecting elements based on a condition. Both are lazy — they do not execute until a terminal operation such as collect() is called.

Syntax

let doubled: Vec<i32> = vec![1, 2, 3].iter().map(|x| x * 2).collect();

// filter(): Keeps only the elements that satisfy the condition.
let evens: Vec<i32> = vec![1, 2, 3, 4, 5].iter().filter(|x| **x % 2 == 0).collect();

// filter_map(): Combines filter and map — discards None and unwraps Some values.
let parsed: Vec<i32> = vec!["1", "abc", "3"]
    .iter()
    .filter_map(|s| s.parse::<i32>().ok())
    .collect();

// Methods can be chained together.
let result: Vec<i32> = (1..=10)
    .filter(|x| x % 2 == 0) // Keep even numbers only.
    .map(|x| x * x) // Square each element.
    .collect();

Method List

MethodDescription
iter.map(|x| ...)Returns a new iterator with each element transformed by the closure.
iter.filter(|x| ...)Returns an iterator containing only the elements that satisfy the condition.
iter.filter_map(|x| ...)Returns an iterator that transforms elements and keeps only the Some values.
iter.map_while(|x| ...)Returns an iterator that continues transforming elements as long as the closure returns Some.
iter.flat_map(|x| ...)Returns an iterator that transforms each element and flattens the nested results.
iter.take_while(|x| ...)Returns an iterator that yields elements as long as the condition is true.
iter.skip_while(|x| ...)Returns an iterator that skips elements as long as the condition is true.
iter.cloned()Clones each element of a reference iterator, producing an iterator of type T.
iter.copied()Copies each element of a reference iterator, producing an iterator of type T (requires the Copy trait).

Sample Code

sample_iter_map_filter.rs
fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // map(): Double every element.
    let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
    println!("doubled: {:?}", doubled);

    // filter(): Keep only even numbers (the closure receives &&T).
    let evens: Vec<&i32> = numbers.iter().filter(|x| **x % 2 == 0).collect();
    println!("evens: {:?}", evens);

    // Using copied() yields T instead of &&T.
    let evens2: Vec<i32> = numbers.iter().copied().filter(|x| x % 2 == 0).collect();
    println!("evens2: {:?}", evens2);

    // Chaining filter and map.
    let result: Vec<i32> = numbers.iter()
        .filter(|&&x| x > 5) // Keep numbers greater than 5.
        .map(|&x| x * x) // Square each element.
        .collect();
    println!("filter+map (squares of x>5): {:?}", result);

    // filter_map(): Extract only the values that parse successfully.
    let strs = vec!["42", "abc", "7", "!", "100"];
    let nums: Vec<i32> = strs.iter().filter_map(|s| s.parse().ok()).collect();
    println!("filter_map (parsed): {:?}", nums);

    // take_while() and skip_while().
    let v = vec![1, 2, 3, 10, 4, 5];
    let taken: Vec<&i32> = v.iter().take_while(|&&x| x < 5).collect();
    println!("take_while (x<5): {:?}", taken); // Stops at 10.

    // Apply map to a range.
    let squares: Vec<i32> = (1..=5).map(|x| x * x).collect();
    println!("squares 1–5: {:?}", squares);

    // Convert strings to uppercase.
    let words = vec!["hello", "world", "rust"];
    let upper: Vec<String> = words.iter().map(|s| s.to_uppercase()).collect();
    println!("uppercase: {:?}", upper);
}

Compile with the following command:

rustc iter_map_filter.rs
./iter_map_filter
doubled: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
evens: [2, 4, 6, 8, 10]
evens2: [2, 4, 6, 8, 10]
filter+map (squares of x>5): [36, 49, 64, 81, 100]
filter_map (parsed): [42, 7, 100]
take_while (x<5): [1, 2, 3]
squares 1–5: [1, 4, 9, 16, 25]
uppercase: ["HELLO", "WORLD", "RUST"]

Common Mistakes

Common mistake 1: double reference (&&T) in filter() closures

When iterating over a slice or Vec with iter(), the iterator yields &T. The filter() closure receives another layer of reference, giving &&T. Use pattern matching to dereference cleanly.

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];

    // iter() yields &i32; filter() receives &&i32
    let evens: Vec<&i32> = numbers.iter()
        .filter(|x| **x % 2 == 0) // double dereference
        .collect();
    println!("{:?}", evens); // [2, 4, 6]

    // Use pattern matching for cleaner code
    let evens2: Vec<&i32> = numbers.iter()
        .filter(|&&x| x % 2 == 0)
        .collect();
    println!("{:?}", evens2); // [2, 4, 6]
}

Common mistake 2: iterators are lazy and do nothing without a terminal operation

Rust iterators use lazy evaluation. A map() or filter() call alone does not execute any work. A terminal operation (collect(), for_each(), count(), etc.) is needed to drive execution.

fn main() {
    let data = vec![1, 2, 3];

    // This does nothing — the closure never runs
    let _ = data.iter().map(|x| {
        println!("never printed");
        x * 2
    });

    // collect() drives the iterator — the closure runs now
    let doubled: Vec<i32> = data.iter()
        .map(|x| {
            println!("processing: {}", x);
            x * 2
        })
        .collect();
    println!("{:?}", doubled); // [2, 4, 6]
}

Overview

Rust iterators use lazy evaluation. Calling map() or filter() does not execute immediately — processing begins only when a terminal operation such as collect(), sum(), or count() is called. This avoids creating intermediate collections and keeps processing efficient.

The closure passed to filter() receives &&T (a reference to a reference). To avoid this double-reference, use iter().copied() or into_iter() to obtain an owning iterator before filtering, which makes the code easier to read.

For terminal operations that collect or aggregate results, see Iterator::collect() / count() / sum().

If you find any errors or copyright issues, please .