Start learning free

LESSON 103 OF 414 · ARRAYS I

Vector Length in Rust: len() and the Last Element

Lesson Read the full explanation

We can get the size of a Vec using the .len() method:

let mut our_array = vec![50, 40, 30];

// Printing the size:
println!("{}", our_array.len()); // Output: 3

// Changing the vector:
our_array.pop();

// Printing the new size:
println!("{}", our_array.len()); // Output: 2

Using the size

We can use the size to access items from the end of a vector.

Because vectors are 0-indexed, the index of the last item is size - 1:

let our_array = vec![50, 40, 30];

let size = our_array.len();

// Printing the last item:
println!("{}", our_array[size - 1]); // Output: 30

// Printing the second to last item:
println!("{}", our_array[size - 2]); // Output: 40

Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 3
    Ctrl + Enter to check

    RUST · ARRAYS I

    Array Length in Rust, explained

    What len() does

    The len() method of a Vec returns how many elements it holds. The count is stored with the vector, so asking for it is instant, however long the vector is. The result changes whenever the vector grows or shrinks:

    let mut our_array = vec![50, 40, 30];
    println!("{}", our_array.len());
    
    our_array.pop();
    println!("{}", our_array.len());
    3
    2

    The same method works on fixed-size arrays and on slices, so the habit carries over. An empty vector has length 0, and is_empty() is the idiomatic way to test for it.

    The type of the length

    len() returns a usize, an unsigned integer whose size matches the machine's pointer width. It is the type Rust requires for indexing, which is why you can use the length directly in an index expression without any conversion.

    Because usize is unsigned, it can never be negative. That matters for arithmetic on lengths, covered below.

    Using the length in a loop

    The range 0..ages.len() excludes its upper bound, so it produces exactly the valid indexes. That makes it the standard way to walk over a vector by position:

    let ages = vec![14, 32, 50, 21];
    let mut total = 0;
    for i in 0..ages.len() {
        total += ages[i];
    }
    println!("{}", total);
    117

    Note that len() on the vector counts elements, not characters. For a vector of strings, fruits.len() is the number of strings, while fruits[0].len() is the byte length of the first string: 5 for "mango".

    Reaching items from the end

    Rust has no negative indexes, so there is no shortcut like "index -1 means last". Instead, compute the position from the length. A vector with len() elements has valid indexes 0 to len() - 1, so the last element is at len() - 1, the second to last at len() - 2, and so on:

    let our_array = vec![50, 40, 30];
    let size = our_array.len();
    
    println!("{}", our_array[size - 1]);
    println!("{}", our_array[size - 2]);
    30
    40

    For the last element specifically, last() is often neater. It returns an Option that is None for an empty vector, so it can't panic.

    Gotchas in Rust

    Subtracting from zero

    If the vector is empty, len() - 1 is 0usize - 1. An unsigned number can't go below zero, so the lesson's optimized builds wrap around to a huge number, and a debug build panics with an overflow error instead. Either way, the following index is out of bounds and the program panics. Check is_empty() or use last() when the vector might have no elements.

    With an empty vector the optimized build reports index out of bounds: the len is 0 but the index is 18446744073709551615. A safe version tests first:

    fn show(v: &Vec<i32>) {
        if v.is_empty() {
            println!("empty");
        } else {
            println!("last = {}", v[v.len() - 1]);
        }
        println!("{:?}", v.last());
    }

    Called with vec![5, 6] it prints last = 6 and then Some(6). Called with an empty vector it prints empty and then None. The second line shows the type last() returns: an Option, which holds a value or nothing.

    Using the length itself as an index

    The length is one more than the last valid index. Writing v[v.len()] always panics, with a message such as index out of bounds: the len is 4 but the index is 4.

    Counting from 1 versus 0

    The length counts elements starting from 1, while indexes start from 0. That one-off difference is the source of most off-by-one mistakes with vectors.

    The lesson's exercise

    The starter code defines two immutable vectors: fruits with three strings and ages with four numbers. The exercise asks for three prints.

    1. Print the number of fruits. Call fruits.len() inside println! with the {} placeholder. It prints 3.
    2. Print the last age. With four elements the last valid index is 3, which is ages.len() - 1. It prints 21.
    3. Print the second to last age. Step back one more position with ages.len() - 2. It prints 50.

    The complete code:

    let fruits = vec!["mango", "kiwi", "grapefruit"];
    let ages = vec![14, 32, 50, 21];
    
    println!("{}", fruits.len());
    println!("{}", ages[ages.len() - 1]);
    println!("{}", ages[ages.len() - 2]);

    The output is:

    3
    21
    50

    Neither vector is declared mut, because reading the length and reading elements doesn't change anything.

    Key takeaways

    • v.len() returns the number of elements as a usize.
    • The last valid index is v.len() - 1; v[v.len()] always panics.
    • Rust has no negative indexes, so count back from the length instead.
    • On an empty vector, len() - 1 underflows; guard with is_empty() or use last().
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free