我正在尝试将长数字转换为字符串向量。例如,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)
答案 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<_>>();
不是最好的性能,但读得很好。