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

时间:2019-11-19 03:48:32

标签: rust iterator

此代码:

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,但也许有一种更好的方法被我忽略了。

1 个答案:

答案 0 :(得分:5)

正如他们所说,这很复杂。如果您的字符串仅是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 u8秒。同时,它有2个char。因此,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的枚举字符迭代器,那么您就自己了。