0Pricing
Learn Rust Coding · Lesson

map, filter, collect

Transform sequences.

map, filter, collect is a free Learn Rust Coding lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Learn Rust Coding learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Transforming Sequences

Three methods do most of the work in iterator pipelines: map transforms each item, filter keeps some items, and collect gathers results into a collection.

Together they replace many manual loops with short, readable chains.

map: One In, One Out

map applies a closure to every item and yields the transformed value. The number of items stays the same; only their values change.

It is lazy, so the closure runs only when the iterator is consumed.

fn main() {
    let nums = vec![1, 2, 3];
    let doubled: Vec<i32> = nums.iter().map(|x| x * 2).collect();
    println!("{:?}", doubled);
}

map Can Change the Type

The output type of map does not have to match the input. Here we turn numbers into strings.

This makes map perfect for converting data from one shape to another.

fn main() {
    let nums = vec![1, 2, 3];
    let labels: Vec<String> = nums.iter().map(|x| format!("n{}", x)).collect();
    println!("{:?}", labels);
}

filter: Keep What You Want

filter takes a closure returning bool. Items where it returns true are kept; the rest are dropped.

The closure receives a reference, so you often dereference with * or use pattern matching.

fn main() {
    let nums = vec![1, 2, 3, 4, 5, 6];
    let evens: Vec<i32> = nums.into_iter().filter(|x| x % 2 == 0).collect();
    println!("{:?}", evens);
}

Chaining map and filter

You can chain adapters freely. Order matters: each item flows through the chain top to bottom.

Here we keep even numbers, then square the survivors.

fn main() {
    let result: Vec<i32> = (1..=6)
        .filter(|x| x % 2 == 0)
        .map(|x| x * x)
        .collect();
    println!("{:?}", result);
}

collect Into a Vec

collect consumes an iterator and builds a collection. Because many collection types are possible, you usually annotate the target type.

The turbofish syntax collect::<Vec<_>>() is an alternative to annotating the variable.

fn main() {
    let squares = (1..=4).map(|x| x * x).collect::<Vec<i32>>();
    println!("{:?}", squares);
}

collect Into a String

collect is not limited to vectors. An iterator of char can collect into a String.

Rust uses the target type to decide how to assemble the items.

fn main() {
    let shouted: String = "hello".chars().map(|c| c.to_ascii_uppercase()).collect();
    println!("{}", shouted);
}

collect Into a HashMap

An iterator of key-value tuples can collect into a HashMap. Pair items with zip or build tuples in a map.

This is a clean way to construct lookups from two parallel sequences.

use std::collections::HashMap;

fn main() {
    let map: HashMap<i32, i32> = (1..=3).map(|x| (x, x * x)).collect();
    println!("{:?}", map.get(&2));
}

Combining All Three

A typical pipeline reads like a sentence: take items, filter them, map them, collect them.

Here we keep words longer than three letters and uppercase them.

fn main() {
    let words = vec!["hi", "rust", "go", "code"];
    let kept: Vec<String> = words
        .into_iter()
        .filter(|w| w.len() > 3)
        .map(|w| w.to_uppercase())
        .collect();
    println!("{:?}", kept);
}

filter_map: Filter and Map at Once

filter_map applies a closure returning Option. Some(v) is kept and unwrapped; None is dropped.

It shines when parsing, where some inputs may be invalid.

fn main() {
    let inputs = vec!["1", "two", "3"];
    let nums: Vec<i32> = inputs
        .into_iter()
        .filter_map(|s| s.parse::<i32>().ok())
        .collect();
    println!("{:?}", nums);
}

Why This Pattern Wins

map/filter/collect pipelines are declarative: they say what you want, not how to loop. They avoid off-by-one bugs and intermediate mutable state.

And thanks to laziness, no temporary vectors are built between the steps.

Quick Check

Check what you know about transforming sequences.

Recap

You can now build real iterator pipelines:

  • map transforms each item and may change its type
  • filter keeps items whose predicate is true
  • collect gathers results into Vec, String, HashMap, and more
  • filter_map filters and maps in one step using Option

Frequently asked questions

Is the “map, filter, collect” lesson free?

Yes — the full text of “map, filter, collect” is free to read here on the web, and the Learn Rust Coding course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Learn Rust Coding course, upgrade to CoddyKit PRO.

What will I learn in “map, filter, collect”?

Transform sequences. You practise Learn Rust Coding with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Learn Rust Coding?

No prior experience is required. Learn Rust Coding on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “map, filter, collect” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Learn Rust Coding lesson?

Yes. Every Learn Rust Coding lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. The Iterator Trait
  2. map, filter, collect
  3. Adapters and Consumers
  4. Custom Iterators
← Back to Learn Rust Coding