Start learning free

LESSON 62 OF 414 · STRINGS I

Updating Strings in Rust: chars(), Vec<char> and collect()

Lesson Read the full explanation

This guided lesson fixes a misspelled name using Rust character collection syntax.


What you will build:

  1. Convert the string to characters, replace the first character with 'A', and collect the characters back into name.

Starter code:

let mut name = "bndrei Chiriac".to_string();

Assignment
Follow the Coding Tutorial and complete the Rust step.

STEP 1 OF 1
    Ctrl + Enter to check

    RUST · STRINGS I

    Updating Strings in Rust, explained

    Strings can't be edited by position

    In some languages strings are immutable and you rebuild them after a change. In Rust a String can change, but not by assigning to a position. This code is rejected:

    let mut name = "bndrei".to_string();
    name[0] = 'A';
    

    The compiler reports the type `str` cannot be indexed by `{integer}`. A Rust string is stored as UTF-8 bytes, and one character can take several of them, so "replace the character at position 0" could change the length of the whole string. Rust avoids the question by not offering positional assignment. You have several explicit ways to produce the changed text.

    The approach in this lesson: go through a vector of characters

    A Vec<char> has one slot per character and supports assignment by index. The pattern has three parts:

    1. Split the string into characters with chars() and gather them with collect().
    2. Edit the vector by index.
    3. Join the characters back into a String with another collect().

    The same method, collect(), does both the first and the last part. It builds whatever collection the surrounding code asks for, so Rust needs to know the target type. In the first call the turbofish collect::<Vec<char>>() names it. In the last call the type comes from the variable being assigned to. A bare let x = chars.iter().collect(); fails with type annotations needed, because nothing says whether you want a vector, a string or something else.

    The lesson's exercise

    Someone saved the name "bndrei Chiriac" with a typo, and the first letter should be A. The starter code has already done the first two parts: it splits name into chars and replaces the first element with 'A'. Your job is the last part: collect the characters back into a string and assign it to name.

    let mut name = "bndrei Chiriac".to_string();
    let mut chars = name.chars().collect::<Vec<char>>();
    chars[0] = 'A';
    name = chars.iter().collect();
    

    After this, name holds Andrei Chiriac. A few details:

    • iter() yields references. Iterating over chars with iter() produces &char values. A String can be built from an iterator of &char as well as of char, so the call works as written. chars.into_iter().collect() also works and consumes the vector.
    • The target type is the variable. Because name is a String, collect() builds a String. The same assignment to a variable of another type would build something else, or fail to compile.
    • let mut is required twice. chars is mutable so that chars[0] = 'A' is allowed, and name is mutable so that it can be given a new value. Without mut on name, the compiler reports cannot assign twice to immutable variable.
    • The first borrow is over. name.chars() only borrows name for the duration of the statement, and the collected vector owns its characters, so assigning to name afterwards is fine.

    Other ways to change a string

    The vector route is the most general, but Rust has shorter tools for specific edits:

    GoalCodeResult
    Replace a byte ranges.replace_range(0..1, "A")the first character becomes A
    Replace matching text"bndrei".replace("bn", "An")a new String, Andrei
    Build from a sliceformat!("A{}", &t[1..])a new String, Andrei
    Add at the ends.push('!')the String grows in place
    Insert at a byte positions.insert(0, '>')the String grows in place
    Remove the last characters.pop()returns an Option<char>
    Empty its.clear()an empty String

    Methods that change the string in place need a mut variable. Methods like replace return a new string and leave the original as it was.

    Common mistakes

    • Indexing the string. name[0] doesn't compile for reading or for writing.
    • Forgetting the type for collect(). Name it with the turbofish or with a type annotation.
    • Using byte positions on non-ASCII text. replace_range, insert and slices count bytes and panic if a position falls inside a character. The vector route counts characters.
    • Expecting the original to change. Editing the vector never touches name until you collect and assign.

    Key takeaways

    • Rust strings can't be changed by index; convert to Vec<char>, edit, and collect back.
    • collect() needs a known target type, from a turbofish or the variable it is assigned to.
    • Both the vector and the string must be mut in this pattern.
    • Shorter in-place tools exist, such as push, insert, replace_range and clear.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free