RustArena

Step 3 of 7

Looping: &v, &mut v and v

There are three ways to loop over a vector, and they match the three ways to use any value in Rust: borrow it, borrow it mutably, or take ownership.

fn main() {
    let mut prices: Vec<u32> = vec![1200, 450, 999];

    let mut total = 0;
    for p in &prices {
        total += *p;
    }
    println!("total {total}");

    for p in &mut prices {
        *p = *p * 9 / 10;
    }
    println!("{:?}", prices);

    for p in prices {
        println!("{p}");
    }
}
total 2649
[1080, 405, 899]
1080
405
899
Loop Each p is The vector afterwards
for p in &prices &u32, a shared reference unchanged, still usable
for p in &mut prices &mut u32, a mutable reference changed in place, still usable
for p in prices u32, the value itself moved: gone after the loop

You'll also see the method forms prices.iter(), prices.iter_mut() and prices.into_iter(); they mean exactly the same three things.

When you need the position too

.iter().enumerate() gives you (index, element) pairs, which a for pattern takes apart:

fn main() {
    let runners = vec!["Ana", "Bo", "Cy"];
    for (i, name) in runners.iter().enumerate() {
        println!("{}. {name}", i + 1);
    }
}
1. Ana
2. Bo
3. Cy

That's tidier than for i in 0..runners.len() with runners[i], and clippy suggests it (needless_range_loop). Module 27 covers enumerate and friends properly.

Common mistakes

Your task

Write fn apply_raise(salaries: &mut [u32], percent: u32) that raises every salary in place by percent percent (integer math: s * (100 + percent) / 100). Loop over the slice mutably; don't index.

Challenge 2

Write fn clamp_all(values: &mut [i32], low: i32, high: i32) that changes every value below low to low and every value above high to high, in place. (Sensors sometimes report wild numbers; this keeps them in a sane range.)

Challenge 3

Write a program that reads one temperature per line (like 21.5), stores them in a Vec<f64>, then prints the average with one decimal, followed by each reading (one decimal) and whether it's above, below or equal to the average. You need the average before you can label the readings, which is why they have to be stored first.

For the input 21.5, 19.0, 23.5 print:

average: 21.3
21.5 above
19.0 below
23.5 above

Previous: Reading elements with [] and get Next: Insert, remove, swap, truncate, clear