【问题标题】:How do I get the index from the beginning in a reversed iterator of chars of a string?如何在字符串字符的反向迭代器中从头开始获取索引?
【发布时间】:2019-11-19 03:48:32
【问题描述】:

这段代码:

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

【问题讨论】:

  • 看起来没有更好的方法,因为如果不调用count(显式或隐式),您将无法获取最后一个字符数。

标签: rust iterator


【解决方案1】:

正如他们所说,这很复杂。如果您的字符串仅为 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 的枚举字符迭代器,那么您只能靠自己了。

【讨论】:

  • 谢谢。是的,当我尝试s.chars().enumerate().rev() 时,我遇到了一个错误,说ExactSizeIterator 未实现或其他内容。感谢您的解释,关于核心原因的有趣和大开眼界!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 2020-09-22
  • 2014-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多