How do I change a character in a string?

I have a code like this

fn main() {
    let mut map:String = String::from(
                    "111111111111\n
                     100000000001\n
                     100000000001\n
                     100000000001\n
                     100000000001\n
                     111111111111");
    let mut count = 0;
    for i in map.chars() {
        if i == '1' {
            map.chars().nth(count).unwrap() = 'W';
        }
        else if i == '0' {
            map.chars().nth(count).unwrap() = '.';
        }
        count += 1; 
    }
}

I'm trying to draw a map on the console but this code doesn't change '1's with 'W's and '0's with '.'s. Compiler says 'invalid left-hand side of assignment'. How do I change '1's with 'W's '0's with '.'s?

I also tried 'replace_range' but now compiler says 'mutable borrow occurs here'

Here is the code

fn main() {
let mut map:String = String::from(
                "111111111111\n
                 100000000001\n
                 100000000001\n
                 100000000001\n
                 100000000001\n
                 111111111111");
let mut count:usize = 0;
for i in map.chars() {
    if i == '1' {
        map.replace_range(count..count, "W");
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^mutable borrow occurs here
    }
    count += 1;
    }
}

Do you really need to change characters 1 by 1?
If not, you could use String::replace()

Hi, I think you'd have to do something like this, creating a new string from an iterator.

fn main() {
    let map: String = String::from(
"111111111111\n
100000000001\n
100000000001\n
100000000001\n
100000000001\n
111111111111",
    );

    let mut chars = Vec::new();
    for i in map.chars() {
        let c = if i == '1' {
            'W'
        } else if i == '0' {
            '_'
        } else {
            i
        };
        chars.push(c);
    }

    let changed:String = chars.iter().collect();
    
    println!("{}", changed);
}

Or maybe in a more idiomatic way and saving an iteration :

fn main() {
    let map: String = String::from(
        "111111111111\n
100000000001\n
100000000001\n
100000000001\n
100000000001\n
111111111111",
    );

    let changed: String = map
        .chars()
        .map(|c| {
            if c == '1' {
                'W'
            } else if c == '0' {
                '_'
            } else {
                c
            }
        })
        .collect();

    println!("{}", changed);
}
1 Like

You might want to use a Vec<u8> (or array) instead of a String in this case, if you're only using ASCII characters. Then you could update values in place.

7 Likes

Since it looks like these characters represent something, a more idiomatic approach would be to use an enum rather than either char or u8. You can then implement the Display trait to convert them to a string when needed for human consumption.

6 Likes