Sam*_*ers 27 string indexing rust
我试图在Rust中索引一个字符串,但编译器抛出一个错误.我的代码(Project Euler problem 4,playground):
fn is_palindrome(num: u64) -> bool {
let num_string = num.to_string();
let num_length = num_string.len();
for i in 0 .. num_length / 2 {
if num_string[i] != num_string[(num_length - 1) - i] {
return false;
}
}
true
}
Run Code Online (Sandbox Code Playgroud)
错误:
error[E0277]: the trait bound `std::string::String: std::ops::Index<usize>` is not satisfied
--> <anon>:7:12
|
7 | if num_string[i] != num_string[(num_length - 1) - i] {
| ^^^^^^^^^^^^^
|
= note: the type `std::string::String` cannot be indexed by `usize`
Run Code Online (Sandbox Code Playgroud)
有没有理由String
不能索引?那我该如何访问数据呢?
Chr*_*gan 28
在Rust中执行此类操作的正确方法不是索引而是迭代.这里的主要问题是Rust的字符串以UTF-8编码,UTF-8是Unicode字符的可变长度编码.如果长度可变,则不查看字符串就无法确定第n个字符的存储位置.这也意味着访问第n个字符的运行时间为O(n)!
在这种特殊情况下,您可以迭代字节,因为已知您的字符串只包含字符0-9(迭代字符是更通用的解决方案,但效率稍差).
这是一些实现这个(游乐场)的惯用代码:
fn is_palindrome(num: u64) -> bool {
let num_string = num.to_string();
let half = num_string.len() / 2;
num_string.bytes().take(half).eq(num_string.bytes().rev().take(half))
}
Run Code Online (Sandbox Code Playgroud)
我们同时遍历字符串中的字节前进(num_string.bytes().take(half)
)和后退(num_string.bytes().rev().take(half)
); 这.take(half)
部分是为了减少完成的工作量.然后我们简单地将一个迭代器与另一个迭代器进行比较,以确保在每一步中第n个和第n个最后一个字节是等价的; 如果是,则返回true; 如果没有,那就错了.
Vla*_*eev 23
是的,最近删除了索引到字符串.这样做是因为Rust字符串在内部是UTF-8,所以索引本身的概念是不明显的,人们倾向于滥用它:字节索引很快,但几乎总是不正确 - 当你的文本包含非ASCII符号时,字节索引可能让你进入一个角色,如果你需要文本处理,这是非常糟糕的,而char索引不是免费的,因为UTF-8是可变长度编码.
如果您确定您的字符串仅包含ASCII字符,则可以使用返回字节切片的as_bytes()
type(using &str
方法)或char()
方法i
:
let num_string = num.to_string();
// ...
let b: u8 = num_string.as_bytes()[i];
let c: char = b as char; // if you need to get the character as a unicode code point
Run Code Online (Sandbox Code Playgroud)
如果需要字符索引,则应使用as_bytes()
方法:
num_string.chars().nth(i).unwrap()
Run Code Online (Sandbox Code Playgroud)
Ang*_*gel 20
如果您要查找的内容类似于索引,则可以使用
.chars()
- >返回char
字符串切片的s上的迭代器.
.nth()
- >返回迭代器的第n个元素 Option
现在您可以通过多种方式使用上述方法,例如:
let s: String = String::from("abc");
//If you are sure
println!("{}", s.chars().nth(x).unwrap());
//or if not
println!("{}", s.chars().nth(x).expect("message"));
Run Code Online (Sandbox Code Playgroud)
小智 8
您可以将 aString
或&str
a转换vec
为 a 字符,然后索引该vec
.
例如:
fn main() {
let s = "Hello world!";
let my_vec: Vec<char> = s.chars().collect();
println!("my_vec[0]: {}", my_vec[0]);
println!("my_vec[1]: {}", my_vec[1]);
}
Run Code Online (Sandbox Code Playgroud)
这里有一个活生生的例子