← Back to Rust Course | Chapter 14: Closures, Iterators & Async | Lesson 3 of 6

map, filter, and collect

map, filter, and collect let you transform, pick out, and finally gather items from a list, one clean step at a time.
Syntax
rust
let result: Vec<Type> = collection
    .iter()
    .map(|x| expression)
    .filter(|x| condition)
    .collect();

Transforming with map

.map() applies a closure to every element of an iterator, producing a new iterator of the transformed results without modifying the original collection.

Example: Transforming with map

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `numbers`, set to `vec![1, 2, 3, 4]`
    let numbers = vec![1, 2, 3, 4];
    // Declare an immutable variable `squared` (a `Vec<i32>`), set to `numbers.iter().map(|n| n * n).collect()`
    let squared: Vec<i32> = numbers.iter().map(|n| n * n).collect();
    // Print "{:?}" to the console, substituting in `squared` (with a trailing newline)
    println!("{:?}", squared);
}

Selecting with filter

.filter() keeps only the elements for which the given closure returns true, discarding everything else from the resulting iterator.

Example: Selecting with filter

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `numbers`, set to `vec![1, 2, 3, 4, 5, 6]`
    let numbers = vec![1, 2, 3, 4, 5, 6];
    // Declare an immutable variable `evens` (a `Vec<&i32>`), set to `numbers.iter().filter(|&&n| n % 2 == 0).collect()`
    let evens: Vec<&i32> = numbers.iter().filter(|&&n| n % 2 == 0).collect();
    // Print "{:?}" to the console, substituting in `evens` (with a trailing newline)
    println!("{:?}", evens);
}

Gathering Results with collect

.collect() consumes an iterator and gathers its elements into a concrete collection type, such as Vec<T> or a String, inferred from context or an explicit type annotation.

Example: Gathering Results with collect

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `words`, set to `vec!["Rust", "is", "fun"]`
    let words = vec!["Rust", "is", "fun"];
    // Declare an immutable variable `joined` (a String), set to `words.iter().map(|w| w.to_uppercase()).collect::<Vec<String>>().join(" ")`
    let joined: String = words.iter().map(|w| w.to_uppercase()).collect::<Vec<String>>().join(" ");
    // Print "{}" to the console, substituting in `joined` (with a trailing newline)
    println!("{}", joined);
}

Chaining map and filter Together

.map() and .filter() can be chained in sequence to express a multi-step transformation clearly and efficiently, since both are lazy and only run once .collect() consumes the pipeline.

Example: Chaining map and filter Together

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `numbers`, set to `vec![1, 2, 3, 4, 5, 6, 7, 8]`
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8];
    // Declare an immutable variable `result` (a `Vec<i32>`), set to `numbers.iter().filter(|&&n| n % 2 == 0).map(|n| n * 10).collect()`
    let result: Vec<i32> = numbers.iter().filter(|&&n| n % 2 == 0).map(|n| n * 10).collect();
    // Print "{:?}" to the console, substituting in `result` (with a trailing newline)
    println!("{:?}", result);
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting to call .collect() (or another consuming method) at the end of a chain, since .map()/.filter() alone produce a lazy iterator, not a final collection.
  2. Not annotating the target type for .collect() when it cannot be inferred, leading to a compile error about an ambiguous type.
  3. Chaining .filter() after .map() when filtering first would avoid transforming elements that will just be thrown away.
Chapter Summary
  • .map(closure) transforms each element of an iterator, producing a new iterator of transformed values.
  • .filter(closure) keeps only the elements for which the closure returns true.
  • .collect() consumes an iterator and gathers its items into a concrete collection, like Vec<T>.
  • These three methods are commonly chained together to express a full data transformation pipeline concisely.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.