Map, filter and collect
Adapters turn one iterator into another. Consumers run the iterator and give you a result.
map
map changes each item with a closure. You get the same number of items out as went in. collect() gathers the results into a Vec; more on it below.
let v = vec![1, 2, 3];let d: Vec<i32> = v.iter().map(|x| x * 2).collect();println!("{:?}", d); // [2, 4, 6]filter
filter keeps only the items where the closure returns true. The closure gets a reference to each item, so you may need *x to compare, like *x > 2.
let v = vec![1, 2, 3, 4];let even: Vec<i32> = v .into_iter() .filter(|x| x % 2 == 0) .collect();println!("{:?}", even); // [2, 4]collect
collect builds a collection, like a Vec or a String, from an iterator. It can build many types, so you must say which one. Without a type, you get "type annotations needed" (E0282 or E0283). In Vec<_>, the _ lets Rust work out the item type for you.
let a: Vec<i32> = v.iter().map(|x| x + 1).collect();let b = v.iter().map(|x| x + 1).collect::<Vec<i32>>();let s: String = vec!['h', 'i'].iter().collect();sum, count, min, max
These consumers turn an iterator into one value.
sum()adds the items; give the result a type, likelet t: i32.count()gives how many items there are.min()andmax()return anOption, because the iterator may be empty.
let v = vec![3, 9, 2];let t: i32 = v.iter().sum(); // 14println!("{:?}", v.iter().max()); // Some(9)enumerate and zip
enumerate pairs each item with its index, starting at 0. zip walks two iterators side by side and stops when the shorter one ends.
let v = vec!['a', 'b'];for (i, c) in v.iter().enumerate() { println!("{i}: {c}"); // 0: a, 1: b}let n = vec![1, 2, 3];let z: Vec<_> = n.iter().zip(v.iter()).collect();Remember
mapchanges items;filterdrops items.collectneeds a type:let v: Vec<_> = ....minandmaxgive anOption.zipstops at the shorter iterator.