Reputation: 21871
This code:
let s = String::from("hi");
for (idx, ch) in s.chars().rev().enumerate() {
println!("{} {}", idx, ch);
}
prints
0 i
1 h
but I want to know the real index, so that it would print:
1 i
0 h
What's the best way to do that? Currently I only think of first getting .count()
and subtracting each idx
from it, but maybe there's a better method that I overlooked.
Upvotes: 4
Views: 1007
Reputation: 13942
This is complicated, as they say. If your string is ASCII only, you can do the obvious enumeration then reverse against a String
's byte iterator:
fn main() {
let s = String::from("hi");
for (idx, ch) in s.bytes().enumerate().rev() {
println!("{} {}", idx, ch as char);
}
}
This doesn't work for Unicode strings in general because of what a char
in Rust stands for:
The
char
type represents a single character. More specifically, since 'character' isn't a well-defined concept in Unicode, char is a 'Unicode scalar value', which is similar to, but not the same as, a 'Unicode code point'.
This can be illustrated by the following:
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);
}
}
This weird looking string has length of 3, as in 3 u8
s. At the same time it has 2 char
s. So ExactSizeIterator
can't be trivially implemented for std::str::Chars
, but it can and does be implemented for std::str::Bytes
. This is significant because to reverse a given iterator, it has to be DoubleEndedIterator
:
fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator,
But DoubleEndedIterator
is only available for enumeration iterator if the underlying iterator is also ExactSizeIterator
:
impl<I> DoubleEndedIterator for Enumerate<I>
where
I: ExactSizeIterator + DoubleEndedIterator,
In conclusion, you can only do s.bytes().enumerate().rev()
, but not s.chars().enumerate().rev()
. If you absolutely have to index the enumerated char iterator of a String
that way, you are on your own.
Upvotes: 5