这段代码:
let s = String::from("hi"); for (idx, ch) in s.chars().rev().enumerate() { println!("{} {}", idx, ch); }
版画
let s = String::from("hi"); for (idx, ch) in s.chars().rev().enumerate() { println!("{} {}", idx, ch); }
但我想知道真实的索引,以便它可以打印:
0 i
1 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字符串,因为char
Rust中的a代表:
该
char
类型表示一个字符。更具体地说,由于“字符”不是Unicode中定义明确的概念,因此char是一个“ Unicode标量值”,它与“ Unicode代码点”相似但不相同。
这可以用以下示例说明:
fn main() { let s = String::from("hi"); for (idx, ch) in s.bytes().enumerate().rev() { println!("{} {}", idx, ch as char); } }
看起来很奇怪的字符串的长度为3,如3 u8
s。同时具有2 char
s。因此ExactSizeIterator
不能轻易实现std::str::Chars
,但是可以并且确实可以实现std::str::Bytes
。这很重要,因为要反转给定的迭代器,它必须是DoubleEndedIterator
:
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);
}
}
但是DoubleEndedIterator
仅当基础迭代器也为枚举迭代器时才可用ExactSizeIterator
:
fn rev(self) -> Rev
where
Self: DoubleEndedIterator,
总之,您只能做s.bytes().enumerate().rev()
,但不能s.chars().enumerate().rev()
。如果您绝对必须以String
这种方式索引枚举的char迭代器,那么您就自己了。