Rust:将字符串拆分以获取单词及其位置

6
Rust有内置函数可将字符串按空格分割,类似于:
let mut iter = " Hello world".split_whitespace();

assert_eq!(Some("Hello"), iter.next());
assert_eq!(Some("world"), iter.next());

然而,我希望有一种方法将字符串拆分为单词,并附上它们在字符串中的相应位置。
let mut iter = ??????(" Hello world");

assert_eq!(Some((1, "Hello")), iter.next());
assert_eq!(Some((7, "world")), iter.next());

考虑到以下问题:

  • 内置的splitsplit_whitespace函数“消耗”了空格,所以我不知道在给定元素之前有多少空格。我应该从split('')开始,并以某种方式将非空格字符“组合”在一起吗?

  • 有一个match_indices函数可以执行类似的操作,但它只能查找给定字符串或使用闭包查找字符。

是否有内置的方法解决这个问题?还是我需要迭代一个std::str::Chars迭代器?

如果是这样,如何从给定字符的Chars迭代器转换为表示下一个单词的字符串?是否有安全的方法从函数中返回它?(编译器迄今为止从未让我这样做)


有一个名为match_indices的函数可以完成类似的功能,但它只能查找给定字符串或字符(使用闭包)。模式也可以是单个字符。无论如何,match_indices有什么问题? - Stargateur
就我所阅读的match_indices文档而言,它似乎不能让你要求“将字符串按所有非空格字符组进行拆分,并给出每个组的第一个元素的索引”。难道它可以吗? - phtrivier
我从未使用过 match_indices... 我认为它并不常用,如果你想进行真正的解析,我建议使用 nom 6。 - Stargateur
1个回答

8
您可以利用split_whitespace()返回指向原始切片的切片,通过计算每个子切片与原始切片地址之间的距离来计算所需索引。
fn addr_of(s: &str) -> usize {
    s.as_ptr() as usize
}

fn split_whitespace_indices(s: &str) -> impl Iterator<Item = (usize, &str)> {
    s.split_whitespace()
        .map(move |sub| (addr_of(sub) - addr_of(s), sub))
}

fn main() {
    let mut iter = split_whitespace_indices(" Hello world");

    assert_eq!(Some((1, "Hello")), iter.next());
    assert_eq!(Some((7, "world")), iter.next());
}

我认为这对于Unicode字符将会失败(例如,“λello world”)。 - lpiepiora
2
@lpiepiora,没有理由它会失败,你为什么这么认为?https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bd71e2100b7368caf89d5e42ec5afca7 - Stargateur
1
它不会失败,它将返回字节索引。这与其他返回字符串索引的函数(例如char_indices()match_indices())保持一致,并且是对str切片操作的期望。 - user4815162342
2
在这种情况下,我认为在“work”周围使用引号是没有正当理由的。返回的索引是您需要使用通常的切片操作从原始字符串获取子字符串的索引,因此对于任何代码点来说都是完全正确的。char_indices()文档没有警告索引,而是警告迭代器生成的字符,它们始终是单个代码点而不是字形。该函数不会将字符串拆分为单个代码点,而仅将其拆分为仅由空格分隔的子字符串,因此它根本没有这个问题。 - user4815162342
3
@phtrivier,只是为了澄清一下,如果您不是以英语为母语的话,“scare quotes”是一个英语习语。我并不是想暗示您真的试图吓唬某人。 :) - user4815162342
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接