Step 7 of 7
A Vec of structs
Most real vectors hold structs: students in a grade book, items in an inventory, orders in a queue. Everything from this module works the same way.
struct Student {
name: String,
score: u32,
}
fn main() {
let mut class = Vec::with_capacity(3);
class.push(Student { name: String::from("Ana"), score: 91 });
class.push(Student { name: String::from("Bo"), score: 78 });
class.push(Student { name: String::from("Cy"), score: 85 });
for s in &mut class {
s.score = (s.score + 5).min(100);
}
class.sort_by(|a, b| b.score.cmp(&a.score));
for (i, s) in class.iter().enumerate() {
println!("{}. {} {}", i + 1, s.name, s.score);
}
let best = &class[0];
println!("best: {}", best.name);
}
1. Ana 96
2. Cy 90
3. Bo 83
best: Ana
for s in &mut classgives a&mut Studenteach time, ands.score = ...changes the student inside the vector. (Field access through a reference doesn't need*: Rust follows the reference for you.).min(100)caps the curved score at 100.sort_bycompares thescorefields. Structs have no built-in order, so you say which field to sort by.&class[0]borrows the best student instead of moving it out.
with_capacity
Vec::with_capacity(n) allocates room for n elements up front. The vector is still empty (len() == 0), but the first n pushes won't need to grow it. When you know roughly how many elements are coming (the number of lines in a file, the size of another collection), it saves allocations. It's a performance hint, never required for correctness.
Common mistakes
Moving a struct out by index:
let top = class[0];iscannot move out of index of Vec<Student>. Use&class[0].sort()on structs:struct Student { name: String, score: u32, } fn main() { let mut class = vec![Student { name: String::from("Ana"), score: 91 }]; class.sort(); println!("{} {}", class[0].name, class[0].score); }error[E0277]: the trait bound `Student: Ord` is not satisfiedRust doesn't guess whether to sort students by name or by score. Say it:
class.sort_by_key(|s| s.score)orsort_bywith a comparison.Holding a reference while pushing.
let best = &class[0]; class.push(...);and then usingbestfails with E0502, for the same reason as pushing inside a loop.
Your task
Write fn restock_list(items: &[Item], min_qty: u32) -> Vec<String> that returns the names of the items whose quantity is below min_qty, in alphabetical order. You'll need owned Strings for the result, so push item.name.clone().
Challenge 2
Write fn most_valuable(items: &[Product]) -> Option<String> that returns the name of the product with the largest stock value (qty * price_cents), or None for an empty slice. On a tie, keep the first one.
Tip: let [first, rest @ ..] = items else { return None; }; handles the empty case and gives you a starting "best" in one line.
Challenge 3
Write a grade book program. Each input line is name score. Store the students in a Vec of a Student struct you define, sort them by score (highest first, equal scores in name order), print them numbered, then print the class average with one decimal:
1. ana 91
2. cy 85
3. bo 78
average: 84.7