如何在字符串字符的反向迭代器中从头开始获取索引



此代码:

let s = String::from("hi");
for (idx, ch) in s.chars().rev().enumerate() {
println!("{} {}", idx, ch);
}

打印

0 i
1 h

但我想知道真正的索引,这样它就会打印出来:

1 i
0 h

最好的方法是什么?目前我只想先得到.count(),然后从中减去每个idx,但可能有一个更好的方法我忽略了。

正如他们所说,这很复杂。如果您的字符串仅为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类型表示单个字符。更具体地说,由于"character"在Unicode中不是一个定义良好的概念,因此char是一个"Unicode标量值",与"Unicode代码点"相似,但不相同。

这可以通过以下内容来说明:

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个u8秒。同时它有2个char秒。因此ExactSizeIterator不能简单地为std::str::Chars实现,但它可以而且确实为std::str::Bytes实现。这很重要,因为要反转给定的迭代器,它必须是DoubleEndedIterator:

fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator,

但是,如果底层迭代器也是ExactSizeIterator:,则DoubleEndedIterator仅可用于枚举迭代器

impl<I> DoubleEndedIterator for Enumerate<I>
where
I: ExactSizeIterator + DoubleEndedIterator,

总之,你只能做s.bytes().enumerate().rev(),而不能做s.chars().enumerate().rev()。如果您必须以这种方式对String的枚举字符迭代器进行索引,那么您就只能靠自己了。

最新更新