如何在rust中迭代str或String的前缀和后缀?

Posted

技术标签:

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

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

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

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

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

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

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

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

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

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

【问题讨论】:

你没有说你需要这些做什么,所以不可能知道你想要字节前缀、代码点前缀还是字形前缀。您唯一的示例使用 ASCII,所有这三个东西都是等价的。 【参考方案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 '\\u306' (bytes 1..3) of `y̆`")]
    fn bad_index() 
        let y = "y̆";
        &y[2..];
    

要在代码点级别工作,rust 有:

str.chars() str.char_indices() str.is_char_boundary()

延伸阅读:https://doc.rust-lang.org/book/ch08-02-strings.html

解决方案

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

从最短到最长:

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?

【讨论】:

非常优雅的解决方案,比我预期的要短得多。

以上是关于如何在rust中迭代str或String的前缀和后缀?的主要内容,如果未能解决你的问题,请参考以下文章

在 Rust 中迭代、过滤和映射数据从一个结构到另一个结构

我应该如何使用&str,Option和String编组Rust函数并在C#中使用它?

Rust:如何在第一个 Err 或 None 上短路退出迭代器方法链?

Rust 的 `String` 和 `str` 有啥区别?

Rust 从对的迭代器中收集哈希图

将 Vec<String> 转换为 Rust 中的 &str 切片?