Start learning free

LESSON 275 OF 679 · TUPLES, SORTING & BUILT-INS

Min, Max and Sum in Rust: Iterator Built-ins

Lesson Read the full explanation

TL ; DR:

v.iter().min() and v.iter().max() give the smallest and the largest value of a vector, in an Option.

v.iter().sum() adds all the values up.


let prices = vec![4, 9, 2, 7];

println!("{}", prices.iter().min().unwrap());    // 2

println!("{}", prices.iter().max().unwrap());    // 9

let total: i32 = prices.iter().sum();

println!("{}", total);                           // 22


Full lesson:

In Maximum Number In Array, a loop found the largest value. In Sum of Numbers, a loop added numbers up. These jobs come up all the time. Rust iterators have them built in.

  • v.iter().min() finds the smallest value of the vector v.
  • v.iter().max() finds the largest value.
  • v.iter().sum() adds all the values up.

min() and max() return an Option, as in Option & Some. An empty vector has no smallest value, so they give None there. unwrap() takes the value out.

That value is a reference into the vector. Put * in front to get the plain number, as in *v.iter().min().unwrap().

sum() needs to know its number type, as in Vec & Iterators. Write it on the variable, as in let total: i32.

Watch out for an empty vector. There, unwrap() finds None and the program panics. When the vector may be empty, use unwrap_or(&0) for a fallback. sum() of an empty vector is 0.


Your task

minutes holds how many minutes you practiced coding on each day of a week.

Store the shortest day in shortest and the longest day in longest. Store the week's total in total.

Use the built-ins from this lesson. The code at the bottom prints all three.

Expected output:

shortest = 15
longest = 60
total = 235
STEP 1 OF 3
    Ctrl + Enter to check

    RUST · TUPLES, SORTING & BUILT-INS

    Min Max Sum in Rust, explained

    What these built-ins do

    Finding the smallest value, the largest value and the total of a list are jobs that come up all the time, and each takes a small loop to write by hand. Rust iterators have them built in. Start from a vector with iter(), then call one of:

    • min(), which finds the smallest value;
    • max(), which finds the largest value;
    • sum(), which adds all the values up.
    let prices = vec![4, 9, 2, 7];
    
    println!("{}", prices.iter().min().unwrap());
    println!("{}", prices.iter().max().unwrap());
    
    let total: i32 = prices.iter().sum();
    println!("{}", total);
    2
    9
    22

    min and max return an Option

    An empty vector has no smallest value, so min() and max() can't always return a number. They return an Option: Some(value) when there is one, None when the vector is empty. On [4, 9, 2, 7] the result of min() is Some(2). The call unwrap() takes the value out of the Some.

    The value inside is a reference into the vector, because iter() borrows the items. Put a * in front to get the plain number:

    let smallest = *prices.iter().min().unwrap();

    Printing with println! works with the reference as it is, as the first example shows. The star matters when you store the number or do arithmetic with it.

    sum needs a type

    Numbers come in several types, and sum() can produce any of them, so it needs to be told which one. The usual way is to write the type on the variable: let total: i32 = prices.iter().sum();. Without it, the compiler stops with "type annotations needed". Another way is prices.iter().sum::<i32>().

    Watch out for an empty vector

    On an empty vector, min() and max() give None, and calling unwrap() on None makes the program panic. When the vector may be empty, give a fallback with unwrap_or(&0) instead; the & is there because the value that would be inside is a reference. The sum of an empty vector is not a problem: it is 0.

    For an empty vector of integers, min() and max() both print as None, sum() gives 0, and min().unwrap_or(&0) gives 0.

    What "smallest" means for other types

    The built-ins compare values with their natural order. For numbers that is numeric order. For strings it is alphabetical order, not length: on ["pear", "fig", "banana"], min() gives Some("banana") and max() gives Some("pear"). To pick by another rule, such as the shortest word, the iterator has min_by_key and max_by_key. Decimals (f64) have no natural total order because of NaN, so min() and max() are not available for them directly.

    Compared with a loop

    A hand-written loop finds the same largest value as the built-in: on [4, 9, 2, 7] both give 9. The loop version needs a starting value and an if; the built-in says what you want in one chain, and the Option forces you to think about the empty case. Use the loop when you need extra logic inside it, and the built-in when you only need the answer.

    The exercise, step by step

    minutes holds how many minutes you practiced on each day of a week. The task is to store the shortest day, the longest day and the total, using these built-ins.

    1. Shortest. Call min() on minutes.iter(), then unwrap(), with a * in front, and store it in shortest.
    2. Longest. The same chain with max(), stored in longest.
    3. Total. Call sum() on minutes.iter() and store it in total, declared with the type i32.
    let minutes = vec![25, 40, 15, 60, 30, 45, 20];
    
    let shortest = *minutes.iter().min().unwrap();
    let longest = *minutes.iter().max().unwrap();
    let total: i32 = minutes.iter().sum();
    
    println!("shortest = {}", shortest);
    println!("longest = {}", longest);
    println!("total = {}", total);

    It prints:

    shortest = 15
    longest = 60
    total = 235

    Key takeaways

    • iter().min() and iter().max() return an Option holding a reference; use unwrap() and a * to get the number.
    • iter().sum() needs a type, usually written on the variable.
    • An empty vector makes unwrap() panic for min() and max(), and gives 0 for sum().
    Keep going with Rust500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free