分割字符串并跳过空的子字符串

4

我正在学习Rust并发现了这个问题:

我想通过一个模式将字符串拆分,并删除所有结果子字符串为空的情况。

以下是一个示例:

let s = "s,o,m,e,";
for elem in s.split(",").skip_while(|&x| x.is_empty()) {
    print!(" <{}> ", elem);
    //print!(" <{}>({}) ", elem, elem.is_empty());
}

但结果如下:

 <s>  <o>  <m>  <e>  <> 

我的想法是:由split返回的结构体Split实现了Iterator,该迭代器提供了skip_while。 IntelliSense告诉我闭包中的x的类型为&&str,因此我认为迭代器(类型为&str)中所有的空元素都将被省略。

但它并没有跳过空子字符串。

我还尝试打印is_empty函数的结果。它显示最后一个切片确实为空。如果我改用skip_while |&x| x == "s",它会正确地排除"s"(此处使用is_empty打印):

 <o>(false)  <m>(false)  <e>(false)  <>(true)

那么迭代器中的切片表现出了不同的行为?

为什么会这样,或者我哪里错了?

2个回答

11
如果你只需要省略输入末尾的一个空字符串,只需使用split_terminator,而不是使用split。这个适配器基本上就像split一样,但它将模式参数视为终止符,而不是分隔符,因此输入末尾的空字符串不被视为新元素。
如果你真想跳过所有的空字符串,请继续阅读。
skip_while正如其文档所述(重点在我):

skip_while()接受一个闭包作为参数。它会对迭代器的每个元素调用这个闭包,并忽略直到它返回false的元素。

false被返回后,skip_while()的工作就结束了,余下的元素将被产生。

无论它们在序列中的位置如何匹配谓词的所有元素的过滤工作都是filter的工作:
let s = ",s,o,,m,e,";
for elem in s.split(",").filter(|&x| !x.is_empty()) {
    print!(" <{}> ", elem);
}

以上代码将产生您想要的效果。

请注意,filter 的谓词与 skip_while 相反: 它不是返回应该不被产生的元素的true,而是返回应该产生的元素的 true


3

skip_while方法会在返回false之前忽略所有元素,也就是说它将获取第一个非空字符串之后的所有元素。例如,给定:

let s = ",,s,o,m,e,";

skip_while函数将忽略前两个空字符串但保留最后一个:

let s = ",,s,o,m,e,";
for elem in s.split(",").skip_while(|&x| x.is_empty()) {
    print!(" <{}> ", elem);
}

会打印出:
<s>  <o>  <m>  <e>  <> 

针对您的情况,似乎只需要使用 filter
let s = "s,o,m,e,";
for elem in s.split(",").filter(|&x| !x.is_empty()) {
    print!(" <{}> ", elem);
}

Playground


游乐场

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