在字符处将字符串拆分为 Vec 的最佳方法<String>,当在 Rust 中没有其他字符之前没有环顾四周时?



假设我想在每个'将类似于abc'xyz?'zzz'的字符串拆分为Vec<字符串>,但如果字符前面是?。我想在没有Regex环视的情况下实现这一点,因为我不能相信输入。

我可以假设,输入是与UTF8兼容的。

在Rust中实现这一点的最快(也可能是最节省内存的方式(是什么?

如果下一个Char是',但通过Char比较,当前Char不是?,我想迭代String并将子字符串保存到var中。然后我将把var的值推到Vec<字符串>通过移动。

这是一个好主意吗?或者有更有效的(时间和记忆方面的(方法来实现这一点吗?

实现这一点的最常用方法是将其作为Iterator的实现,采用&str并生成&str

这里有一个示例实现,它假设输入字符串上的尾随'应该而不是在它之后产生一个空元素,空字符串也不应该产生任何元素。请注意,由于我们只处理字符串切片,因此不进行复制。如果您想生成Vec<String>,那么您可以通过将迭代器映射到str::to_owned上来实现。(.map(str::to_owned).collect::<Vec<_>>()(

use std::str::CharIndices;
// A verbose name for an oddly specific concept.
struct SplitStringAtCharNotFollowingCharIterator<'a> {
delimiter: char,
exception: char,
text: &'a str,
chars: CharIndices<'a>,
}
impl<'a> SplitStringAtCharNotFollowingCharIterator<'a> {
pub fn new(text: &'a str, delimiter: char, exception: char) -> Self {
Self { delimiter, exception, text, chars: text.char_indices() }
}
}
impl<'a> Iterator for SplitStringAtCharNotFollowingCharIterator<'a> {
type Item = &'a str;

fn next(&mut self) -> Option<&'a str> {
let first = self.chars.next();

let (start, mut prior) = match first {
None => return None,
Some((_, c)) if c == self.delimiter => return Some(""),
Some(v) => v,
};

loop {
prior = match self.chars.next() {
None => return Some(&self.text[start..]),

Some((end, c)) if c == self.delimiter && prior != self.exception =>
return Some(&self.text[start..end]),

Some((_, c)) => c,
}
}
}
}

(游乐场(

使用它来实现您的既定目标的示例:

let pieces = SplitStringAtCharNotFollowingCharIterator::new("abc'xyz?'zzz'", ''', '?')
.map(str::to_owned)
.collect::<Vec<_>>();

但是,如果您实际上不需要拥有的字符串或向量,您可以直接使用迭代器,因为它会分配原始切片的子切片,所以不需要任何额外的堆分配。

我认为您不需要过度复杂化这一点——一个简单的for循环就可以了。这也可以很容易地准确调整拆分的工作方式,例如包括/排除分隔符、如何处理空匹配。游乐场

fn split(s: &str) -> Vec<String> {
let mut chunks = Vec::new();
let mut cur = String::new();
let mut last_char = None;
for c in s.chars() {
if c == ''' && last_char != Some('?') {
chunks.push(std::mem::take(&mut cur));
} else {
cur.push(c);
}
last_char = Some(c);
}
chunks.push(cur);
chunks
}

如果您想生成Vec<&str>,您需要做更多的工作来维护对现有字符串的引用,但由于我们返回的是Vec<String>,我们可以简单地逐个复制字符。

最新更新