【问题标题】:How to iterate prefixes and suffixes of str or String in rust?如何在rust中迭代str或String的前缀和后缀?
【发布时间】:2021-10-21 00:50:06
【问题描述】:

我有一个字符串:“abcd”,我想:

  • 从最短到最长迭代它的前缀:

    ""、"a"、"ab"、"abc"、"abcd"

  • 从最长到最短迭代它的前缀:

    “abcd”、“abc”、“ab”、“a”、“”

  • 从最短到最长迭代其后缀:

    ""、"d"、"cd"、"bcd"、"abcd"

  • 从最长到最短迭代其后缀:

    “abcd”、“bcd”、“cd”、“d”、“”

【问题讨论】:

  • 你没有说你需要这些做什么,所以不可能知道你想要字节前缀、代码点前缀还是字形前缀。您唯一的示例使用 ASCII,所有这三个东西都是等价的。

标签: string rust iterator prefix suffix


【解决方案1】:

字符串比人们想象的要复杂

  • 为了符合人类直觉,您通常希望将字符串视为由 0 个或多个字素簇组成的序列。
  • 字素簇是 1 个或多个 Unicode 代码点的序列
  • 在 utf8 编码中,代码点表示为 1、2、3 或 4 个字节的序列
  • Rust 中的 String 和 str 都使用 utf8 表示字符串,索引是 byte 偏移量
  • 对代码点的一部分进行切片毫无意义,并且会产生垃圾数据。 Rust 选择恐慌:
#[cfg(test)]
mod tests {
    #[test]
    #[should_panic(expected = "byte index 2 is not a char boundary; it is inside '\\u{306}' (bytes 1..3) of `y̆`")]
    fn bad_index() {
        let y = "y̆";
        &y[2..];
    }
}

解决方案

警告:此代码在代码点级别工作,并且忽略了字素簇。

从最短到最长:

use core::iter;

pub fn prefixes(s: &str) -> impl Iterator<Item = &str> + DoubleEndedIterator {
    s.char_indices()
        .map(move |(pos, _)| &s[..pos])
        .chain(iter::once(s))
}

pub fn suffixes(s: &str) -> impl Iterator<Item = &str> + DoubleEndedIterator {
    s.char_indices()
        .map(move |(pos, _)| &s[pos..])
        .chain(iter::once(""))
        .rev()
}

反过来:

prefixes(s).rev()
suffixes(s).rev()

test

另见:How to iterate prefixes or suffixes of vec or slice in rust?

【讨论】:

  • 非常优雅的解决方案,比我预期的要短得多。
猜你喜欢
  • 2021-10-20
  • 2010-10-25
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多