如何以函数式的方式将字符串向量转换为整数向量?

10

我试图将Vec<&str>转换为Vec<u16>,但我无法找到一种功能性的方法来实现它。

let foo: &str = "1,2,3"; // Parsing a string here
let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's

我需要将bar存入一个Vec<u16>中。

3个回答

18

有一个迭代器适配器map!你可以这样使用它:

let bar: Vec<u16> = foo.split(",").map(|x| x.parse::<u16>().unwrap()).collect();

parse 是一个依赖于特质 FromStr 的库函数,它可能会返回一个错误,因此我们需要 unwrap() 错误类型。(这对于一个简短的例子来说是一个好主意,但在实际代码中,您将希望正确处理错误——如果那里有一个不是 u16 的值,您的程序将会崩溃)。

map 接受一个通过值传递它的参数并返回通过 惰性 应用该函数获得的迭代器的闭包。你正在collect所有值,但如果你只take(5)其中的五个,你只会解析五个字符串。


10
您还没有完全说明您的问题。具体来说,当其中一个字符串不能被解析为数字时会发生什么?使用parse从字符串中解析数字时,可能会失败。这就是为什么函数返回Result的原因:
fn parse<F>(&self) -> Result<F, F::Err>
where
    F: FromStr,

这里有一个解决方案,它获取向量,并使用 iter 获取迭代器,使用 map 更改每个项目,最终使用 collect 返回一个Result。如果解析成功,则返回Ok。如果任何一个失败,则返回Err
fn main() {
    let input = "1,2,3";
    let strings: Vec<_> = input.split(",").collect();

    let numbers: Result<Vec<u16>, _> = strings.iter().map(|x| x.parse()).collect();

    println!("{:?}", numbers);
}

或者您可以通过使用 flat_map 过滤掉 Err 值来移除失败的转换:

fn main() {
    let input = "1,2,3";
    let strings: Vec<_> = input.split(",").collect();

    let numbers: Vec<u16> = strings.iter().flat_map(|x| x.parse()).collect();

    println!("{:?}", numbers);
}

当然,将字符串转换为字符串向量,然后再将其转换为整数向量有点愚蠢。如果你实际上有一个逗号分隔的字符串并且想要数字,请一次性完成:
fn main() {
    let input = "1,2,3";

    let numbers: Result<Vec<u16>, _> = input.split(",").map(|x| x.parse()).collect();

    println!("{:?}", numbers);
}

另请参阅:


4

作为一个对Rust不是很有经验的人,我的看法如下。

fn main() {
    let foo: &str = "1,2,3"; // Parsing a string here
    let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's

    // here the magic happens
    let baz = bar.iter().map(|x| x.parse::<i64>());

    for x in baz {
        match x {
            Ok(i) => println!("{}", i),
            Err(_) => println!("parse failed"),
        }
    }
}

请注意,由于parse返回一个Result,因此您需要从每个解析的元素中提取值。您可能希望以不同的方式行事,例如仅过滤成功的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接