将int转换为字符串向量

时间:2015-10-04 04:05:02

标签: string vector rust

我正在尝试将长数字转换为字符串向量。例如,17562将成为["1", "7", "5", "6", "2"]。我已经看到很多将int转换为字符串的例子,但没有将字符串向量转换为int。我想分别迭代每个数字。

这是我到目前为止所做的,但它不起作用。

fn main() {
    let x = 42;
    let values: Vec<&str> = x.to_string().split(|c: char| c.is_alphabetic()).collect();
    println!("{:?}", values);     
}

给我编译错误:

<anon>:3:29: 3:42 error: borrowed value does not live long enough
<anon>:3     let values: Vec<&str> = x.to_string().split(|c: char| c.is_alphabetic()).collect();

<anon>:3:88: 6:2 note: reference must be valid for the block suffix following statement 1 at 3:87...
<anon>:3     let values: Vec<&str> = x.to_string().split(|c: char| c.is_alphabetic()).collect();
<anon>:4     println!("{:?}", values);
<anon>:5     
<anon>:6 }
<anon>:3:5: 3:88 note: ...but borrowed value is only valid for the statement at 3:4
<anon>:3     let values: Vec<&str> = x.to_string().split(|c: char| c.is_alphabetic()).collect();

<anon>:3:5: 3:88 help: consider using a `let` binding to increase its lifetime
<anon>:3     let values: Vec<&str> = x.to_string().split(|c: char| c.is_alphabetic()).collect();

我在python中尝试做的相当于x = 42; x = list(str(x)); print(x)

3 个答案:

答案 0 :(得分:6)

好的,第一个问题是你不会将x.to_string()的结果存储在任何地方。因此,它将不再存在于表达式的末尾,这意味着values将尝试引用不再存在的值。因此错误。最简单的解决方案是将临时字符串存储在某处,以便它继续存在:

fn main() {
    let x = 42;
    let x_str = x.to_string();
    let values: Vec<&str> = x_str.split(|c: char| c.is_alphabetic()).collect();
    println!("{:?}", values);     
}

第二个问题:这会输出["42"],因为你告诉它要拆分字母。您可能打算使用is_numeric

fn main() {
    let x = 42;
    let x_str = x.to_string();
    let values: Vec<&str> = x_str.split(|c: char| c.is_numeric()).collect();
    println!("{:?}", values);     
}

第三个问题:这会输出["", "", ""],因为它们是数字字符之间的三个字符串。 Split的参数是分隔符。因此,第三个问题是你开始使用完全错误的方法。

与您列出的Python代码最接近的 direct 将是:

fn main() {
    let x = 42;
    let values: Vec<String> = x.to_string().chars().map(|c| c.to_string()).collect();
    println!("{:?}", values);     
}

最后,输出:["4", "2"]

但是,这非常低效:它接受整数,分配一个中间缓冲区,将整数打印到它,将其转换为字符串。它接受该字符串中的每个代码点,分配一个中间缓冲区,将代码点打印到它,将其转换为字符串。然后它将所有这些字符串收集到Vec中,可能会多次重新分配。

有效,但有点浪费。如果你不关心浪费,你现在就可以停止阅读了。

通过收集代码点而不是字符串,您可以减少浪费:

fn main() {
    let x = 42;
    let values: Vec<char> = x.to_string().chars().collect();
    println!("{:?}", values);     
}

输出:['4', '2']。请注意不同的引号,因为我们使用的是char而不是String

我们可以通过预先分配其存储来从Vec大小调整中删除中间分配,这为我们提供了这个版本:

fn main() {
    let x = 42u32; // no negatives!
    let values = {
        if x == 0 {
            vec!['0']
        } else {
            // pre-allocate Vec so there's no resizing
            let digits = 1 + (x as f64).log10() as u32;
            let mut cs = Vec::with_capacity(digits as usize);
            let mut div = 10u32.pow(digits - 1);
            while div > 0 {
                cs.push((b'0' + ((x / div) % 10) as u8) as char);
                div /= 10;
            }
            cs
        }
    };
    println!("{:?}", values);     
}

除非你在循环中这样做,否则我只会坚持使用正确,浪费的版本。

答案 1 :(得分:3)

如果您正在寻找高性能版本,我只需使用此

fn digits(mut val: u64) -> Vec<u8> {
    // An unsigned 64-bit number can have 20 digits
    let mut result = Vec::with_capacity(20);

    loop {
        let digit = val % 10;
        val = val / 10;
        result.push(digit as u8);

        if val == 0 { break }
    }

    result.reverse();
    result
}

fn main() {
    println!("{:?}", digits(0));
    println!("{:?}", digits(1));
    println!("{:?}", digits(9));
    println!("{:?}", digits(10));
    println!("{:?}", digits(11));
    println!("{:?}", digits(1234567890));
    println!("{:?}", digits(0xFFFFFFFFFFFFFFFF));
}

这可能过度分配几个字节,但总共20个字节很小,除非你这样做整个束。它还将每个值保留为数字,您可以根据需要将其转换为字符串。

答案 2 :(得分:1)

怎么样:

let ss = value.to_string()
              .chars()
              .map(|c| c.to_string())
              .collect::<Vec<_>>();

Demo

不是最好的性能,但读得很好。