Start learning free

LESSON 101 OF 414 · ARRAYS I

Updating Array and Vec Elements in Rust

Lesson Read the full explanation

The entries of an array declared with mut can be changed freely, using indices and the bracket notation:

let mut our_array = [50, 40, 30];
our_array[0] = 15;
our_array[1] = -1;

// our_array is now [15, -1, 30]

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

    Updating Static Array Elements in Rust, explained

    Elements can be assigned

    You change an element by assigning to its index. The target of the assignment is the same bracket expression you use for reading:

    let mut our_array = [50, 40, 30];
    our_array[0] = 15;
    our_array[1] = -1;
    
    // our_array is now [15, -1, 30]
    

    The array stays the same length and keeps its element type. Only the values at those positions are replaced. The same code works on a Vec.

    The key detail is let mut. In Rust a variable is immutable unless declared with mut, and that covers every element inside it. Without mut, a[0] = 5; doesn't compile: the compiler says it cannot assign to a[_] because a is not declared as mutable, and suggests adding mut.

    Compound assignment

    Operators such as +=, -= and *= work on elements. ages[1] += 5 reads the element, adds 5 and stores the result back in the same position. It is shorthand for ages[1] = ages[1] + 5.

    The type must match

    An element can only be replaced by a value of the element type. This matters for text. A vector created with "mango".to_string() holds String values, owned and growable text, not &str slices. Assigning a bare literal to one of its slots is an error:

    expected `String`, found `&str`
    

    Convert the literal first with .to_string(), as in fruits[0] = "apple".to_string();. A literal like "apple" has type &str, a borrowed view of text stored in the program, so it has to become an owned String before it can live in a Vec<String>.

    The lesson's exercise

    The starting code is:

    let mut fruits = vec!["mango".to_string(), "kiwi".to_string(), "grapefruit".to_string()];
    let mut ages = vec![14, 32, 50, 21];
    

    Both are declared with mut, so their elements can change.

    1. Replace the first fruit. Assign to fruits[0] with "apple".to_string(). The vector becomes apple, kiwi, grapefruit.
    2. Add 5 to the second age. Index 1 holds 32, and ages[1] += 5 makes it 37.
    3. Verify both changes. Print 1 if the check passes and 0 otherwise. In Rust, if condition { 1 } else { 0 } is an expression, so it can be passed straight to println!. The first check is ages[1] == 37. The second joins three comparisons with &&, one per fruit. A String can be compared with a string literal using ==.
    let mut fruits = vec!["mango".to_string(), "kiwi".to_string(), "grapefruit".to_string()];
    let mut ages = vec![14, 32, 50, 21];
    
    fruits[0] = "apple".to_string();
    ages[1] += 5;
    
    println!("{}", if ages[1] == 37 { 1 } else { 0 });
    println!("{}", if fruits[0] == "apple" && fruits[1] == "kiwi" && fruits[2] == "grapefruit" { 1 } else { 0 });
    

    Both lines print 1. The two branches of each if have the same type, which is required for it to be used as a value.

    Common mistakes

    • Forgetting mut. Assignment to an element of an immutable binding doesn't compile.
    • Assigning a &str to a String slot. Add .to_string() (or use String::from).
    • Using = where you mean ==. = assigns, and == compares. The checks must use ==.
    • Wrong index. The first item is at index 0 and the second at index 1. An index past the end panics at run time.
    • Expecting a change in a copy. Arrays of integers are copied when assigned to a new variable. After let mut b = a;, changing b[0] doesn't change a. A vector is moved, not copied, on assignment, so the old name can't be used afterwards.

    Key takeaways

    • Assign to an element with v[i] = value, and update it in place with v[i] += n.
    • The variable must be declared with let mut.
    • The new value must have the element type, so a Vec<String> needs .to_string() on literals.
    • if ... { 1 } else { 0 } is a value, which makes small checks easy to print.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free