简体   繁体   中英

how to convert a Vec<&str> to Vec<usize>

I'm new to rust programming language. I was trying to covert Vec<&str> to Vec
but I get the below error. I don't know the reason for that. is anyone there to help me understand why this happens.

my code:

   let result: Vec<usize> = "123456789"    
              .split("") 
              .map(|x| x.parse::<usize>().unwrap())  
              .collect();

the error

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: Empty }', src/main.rs:92:37
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

According to https://doc.rust-lang.org/std/primitive.str.html#method.split :

When the empty string is used as a separator, it separates every character in the string, along with the beginning and end of the string.

let f: Vec<_> = "rust".split("").collect();
assert_eq!(f, &["", "r", "u", "s", "t", ""]);

So your split does not do what you think it does, as it prepends and appends an empty string, which fail to be parsed as an integer.

There are a few different ways to do what you want here, for example, you can just ignore the invalid conversions by using flat_map:

let result: Vec<usize> = "123456789"    
          .split("")
          .flat_map(|x| x.parse::<usize>())  
          .collect();

You can also not use split, but iterate on chars instead, and use the char::to_digit method:

let result: Vec<usize> = "123456789"    
          .chars()
          .flat_map(|c| c.to_digit(10))
          .map(|n| n as usize)
          .collect();

Note that these examples avoid using unwrap so these will never panic, even if the input string is invalid.

An approach that allows you to get an error in case of problem could be the following:

let result: Result<Vec<usize>, String> = "123456789"
    .chars()
    .map(|c| {
        c.to_digit(10)
            .map(|n| n as usize)
            .ok_or(format!("invalid digit: {c}"))
    })
    .collect();

The problem is that you are getting things that you cannot parse. Check this example:

fn main() {
    let result: Vec<_> = "123456789"
        .split("")
        .collect();
    println!("{result:?}");
}

which outputs:

["", "1", "2", "3", "4", "5", "6", "7", "8", "9", ""]

You can filter those empty strings ( "" ) first for solving your problem:

let result: Vec<usize> = "123456789"    
          .split("")
          .filter(|x| !x.is_empty())
          .map(|x| x.parse::<usize>().unwrap())  
          .collect();

Playground

You can also use the str::chars method, and then the char::to_digit :

fn main() {
    let result: Vec<usize> = "123456789"
        .chars()
        .map(|x| x.to_digit(10).unwrap() as usize)
        .collect();
}

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM