Lesson 8 of 12
Collections & Iterators
Learn the standard collections and how to them with . A chain of map, filter and sum compiles to code as fast as a hand-written .
use std::collections::{HashMap, HashSet, BTreeMap, VecDeque};
fn main() {
// Vec — growable array, the workhorse
let mut nums = vec![3, 1, 4, 1, 5];
nums.push(9);
nums.sort();
nums.dedup();
println!("{:?}", nums); // [1, 3, 4, 5, 9]
println!("{:?}", nums.first()); // Some(1) — never panics
println!("{:?}", nums.get(99)); // None — unlike nums[99]
// HashMap
let mut scores: HashMap<String, i32> = HashMap::new();
scores.insert("ada".to_string(), 10);
// entry() is the idiomatic get-or-insert
*scores.entry("ada".into()).or_insert(0) += 5;
*scores.entry("bob".into()).or_insert(0) += 1;
println!("{:?}", scores.get("ada")); // Some(15)
for (name, score) in &scores {
println!("{name}: {score}");
}
// HashSet for membership, BTreeMap for sorted keys, VecDeque for a queue
let seen: HashSet<i32> = nums.iter().copied().collect();
let sorted: BTreeMap<&str, i32> = BTreeMap::from([("b", 2), ("a", 1)]);
let mut queue: VecDeque<i32> = VecDeque::from([1, 2, 3]);
queue.push_back(4);
println!("{:?} {:?} {:?}", seen.contains(&4), sorted.keys().collect::<Vec<_>>(), queue.pop_front());
}#[derive(Debug, Clone)]
struct Order { customer: String, region: String, total: f64 }
fn main() {
let orders = vec![
Order { customer: "Ada".into(), region: "EU".into(), total: 120.5 },
Order { customer: "Bob".into(), region: "US".into(), total: 45.0 },
Order { customer: "Cleo".into(), region: "EU".into(), total: 310.75 },
];
// Three ways to iterate — the difference is ownership:
// .iter() -> &T borrow each item
// .iter_mut() -> &mut T borrow mutably
// .into_iter() -> T consume the collection
let total: f64 = orders.iter().map(|o| o.total).sum();
println!("{total:.2}"); // 476.25
let eu_names: Vec<&str> = orders
.iter()
.filter(|o| o.region == "EU")
.map(|o| o.customer.as_str())
.collect();
println!("{eu_names:?}"); // ["Ada", "Cleo"]
// Nothing runs until a consuming adapter: collect, sum, count, for_each, fold
let biggest = orders.iter().max_by(|a, b| a.total.total_cmp(&b.total));
println!("{:?}", biggest.map(|o| &o.customer));
let summary = orders.iter().fold(String::new(), |mut acc, o| {
acc.push_str(&format!("{} ", o.customer));
acc
});
println!("{}", summary.trim());
}use std::collections::HashMap;
fn main() {
let words = ["apple", "banana", "avocado", "blueberry", "cherry"];
// Grouping
let mut by_letter: HashMap<char, Vec<&str>> = HashMap::new();
for w in words {
by_letter.entry(w.chars().next().unwrap()).or_default().push(w);
}
println!("{:?}", by_letter.get(&'a')); // Some(["apple", "avocado"])
// The adapters worth memorising
let nums: Vec<i32> = (1..=10).collect();
println!("{:?}", nums.iter().enumerate().take(2).collect::<Vec<_>>());
println!("{:?}", nums.iter().zip("abc".chars()).collect::<Vec<_>>());
println!("{:?}", nums.iter().skip(8).collect::<Vec<_>>());
println!("{:?}", nums.chunks(3).next());
println!("{:?}", nums.windows(2).next());
println!("{}", nums.iter().any(|&n| n > 9));
println!("{}", nums.iter().all(|&n| n > 0));
println!("{:?}", nums.iter().position(|&n| n == 7));
println!("{:?}", nums.iter().rev().take(3).collect::<Vec<_>>());
// filter_map: filter and transform in one pass
let inputs = ["1", "two", "3"];
let parsed: Vec<i32> = inputs.iter().filter_map(|s| s.parse().ok()).collect();
println!("{parsed:?}"); // [1, 3]
// collect into a Result: fails fast if ANY item fails
let all: Result<Vec<i32>, _> = inputs.iter().map(|s| s.parse::<i32>()).collect();
println!("{}", all.is_err()); // true
}Finished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.