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:
maptransforms each item and may change its typefilterkeeps items whose predicate istruecollectgathers results intoVec,String,HashMap, and morefilter_mapfilters and maps in one step usingOption
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
- The Iterator Trait
- map, filter, collect
- Adapters and Consumers
- Custom Iterators