我在rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
我的目标是将长度为n
的字符串拆分为长度为n-k+1
的{{1}}偏移量子字符串。我的意思是,如果你有一个字符串:
k
我正在尝试获取包含任意长度ABCDEF
的偏移子串的向量/迭代器。例如,k
将产生
k=3
而ABC
BCD
CDE
DEF
会产生:
k=2
请注意,空格仅包含在上方以对齐子字符串以显示它们的相关性。输出向量只包括AB
BC
CD
DE
EF
,AB
,BC
等。此外,只支持ASCII,但我更喜欢更安全,更通用的解决方案。
看起来很痛苦,以下程序代码似乎有效:
CD
但它很讨厌,我更喜欢更实用的解决方案。我花了几个小时试图找到一种方法,并在这个过程中学到了很多东西,但我对这个问题感到难过。
有什么想法吗?
PS - 我真的很惊讶上面的fn offset_slices(s: &str, n: usize) -> Vec<&str> {
let mut slices: Vec<&str> = Vec::new();
for (i,_) in s.chars().enumerate() {
if i > s.len() - n {
break;
}
slices.push(&s[i..(i+n)]);
}
slices
}
甚至编译。它只是返回指向输入的各个位置的指针吗?
答案 0 :(得分:4)
fn offset_slices(s: &str, n: usize) -> Vec<&str> {
(0 .. s.len() - n + 1).map(|i| &s[i .. i + n]).collect()
}
答案 1 :(得分:3)
你真的想要windows
迭代器,但只存在切片而不是字符串(参见下面的注释)。由于您有ASCII数据,我们可以创建一个强制执行该约束的类型,然后使用一些不安全的代码。我们程序员可以保证不安全的代码 安全因为我们确保数据只是ASCII 。
作为huon-dbaupp points out,您应该尝试使用ascii crate。它现在似乎没有windows
,但是如果你愿意的话,你有权将这些代码(适当调整)提交给那个箱子。 ^ _ ^
use std::slice;
use std::str;
struct AsciiString {
bytes: Vec<u8>,
}
impl AsciiString {
fn new(s: &str) -> AsciiString {
for b in s.bytes() {
assert!((b as u8) < 128);
}
AsciiString { bytes: s.bytes().collect() }
}
fn windows(&self, n: usize) -> Windows {
Windows { iter: self.bytes.windows(n) }
}
}
struct Windows<'a> {
iter: slice::Windows<'a, u8>,
}
impl<'a> Iterator for Windows<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.iter.next().map(|bytes| {
unsafe { str::from_utf8_unchecked(bytes) }
})
}
}
fn main() {
let ascii = AsciiString::new("ABCDEF");
for i in ascii.windows(3) {
println!("{}", i);
}
}
我真的很惊讶上面的slices.push(&amp; s [i ..(i + n)])甚至编译。它只是返回指向输入的各个位置的指针吗?
这是一个棘手的问题,但一旦理解了它就有意义了(事情总是如此?)
当您使用Index
特征时,请注意它已针对str
实施,而不是&str
:
fn index(&'a self, index: Idx) -> &'a Self::Output;
impl Index<Range<usize>> for str { ... }
这意味着索引返回值,其生命周期与输入相同。在这种情况下,您从&'foo str
开始,最后得到&'foo str
。从概念上讲,是的,&str
是指向一块内存和一个长度的指针。当你对它进行切片时,你只是调整指针和长度,但底层存储仍将存活相同的生命周期。
每当开始拆分字符串时,请注意字节/字符/代码点/字形的问题。使用比ASCII字符更复杂的字符,一个字符不一个字节,字符串切片操作字节!还有Unicode代码点的概念,但是多个Unicode字符可以组合形成人类认为的单个字符。这个东西非平凡。