我有一个字符串:"abcd"我想:
-
从最短到最长迭代前缀:
"、"a"ab","abc","abcd"
-
从长到短迭代前缀:
"abcd","abc","ab","a",">
-
从最短到最长迭代其后缀:
"、"d"cd","bcd","abcd"
-
从长到短迭代其后缀:
"abcd","bcd","cd","d",">
字符串比人们想象的要复杂得多
- 为了符合人类的直觉,您通常希望将字符串视为0个或多个字形簇的序列。
- 一个字素簇是一个由1个或多个Unicode码点组成的序列
- 在utf8编码中,码点表示为1、2、3或4字节的序列
- rust中的String和str都使用utf8来表示字符串,索引是字节偏移量
- 切片代码点的一部分是没有意义的,并且会产生垃圾数据。Rust选择panic:
#[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..];
}
}
在代码点级别rust有:
- str.chars ()
- str.char_indices ()
- str.is_char_boundary ()
进一步阅读:https://doc.rust-lang.org/book/ch08-02-strings.html
解决方案警告:这段代码在代码点级别上工作,并且是grapheme cluster无关的。
从最短到最长:
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()
测试参见:如何在rust中迭代vec或slice的前缀或后缀?