正如他们所说,这很复杂。如果您的字符串仅为 ASCII,您可以进行明显的枚举,然后逆向 String 的字节迭代器:
fn main() {
let s = String::from("hi");
for (idx, ch) in s.bytes().enumerate().rev() {
println!("{} {}", idx, ch as char);
}
}
这通常不适用于 Unicode 字符串,因为 Rust 中的 char 代表什么:
char 类型表示单个字符。更具体地说,由于“字符”在 Unicode 中不是一个明确定义的概念,因此 char 是一个 'Unicode scalar value',与 'Unicode code point' 相似但不相同。
这可以通过以下方式来说明:
fn main() {
let s = String::from("y̆");
println!("{}", s.len());
for (idx, ch) in s.bytes().enumerate() {
println!("{} {}", idx, ch);
}
for (idx, ch) in s.chars().enumerate() {
println!("{} {}", idx, ch);
}
}
这个看起来很奇怪的字符串长度为 3,如 3 u8s。同时它有2个chars。所以ExactSizeIterator 不能简单地为std::str::Chars 实现,但它可以而且确实可以为std::str::Bytes 实现。这很重要,因为要反转给定的迭代器,它必须是 DoubleEndedIterator:
fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator,
但DoubleEndedIterator只有在底层迭代器也是ExactSizeIterator时才可用于枚举迭代器:
impl<I> DoubleEndedIterator for Enumerate<I>
where
I: ExactSizeIterator + DoubleEndedIterator,
总之,你只能做s.bytes().enumerate().rev(),但不能做s.chars().enumerate().rev()。如果您绝对必须以这种方式索引 String 的枚举字符迭代器,那么您只能靠自己了。