我需要检测并列出切片中重复次数大于或等于 N 次的字符串字符。我已经成功地用 Rust 编写了非高阶函数解决方案(如下),但我想知道这是否可以简化为链接 iter 方法。
想法:
let v = "1122253225";
let n = 2;
输出:
There are 2 repetition of '1'
There are 3 repetition of '2'
There are 2 repetition of '2'
发生重复的索引并不重要。重复必须按顺序发生(即,3 次重复的“2”与其他 2 次重复的“2”被其他值分隔开,算作单独的输出行)。
我的非迭代器解决方案:
let mut cur_ch = '\0';
let mut repeat = 0;
for ch in v.chars() {
if ch == cur_ch {
repeat = repeat + 1;
}
else {
if repeat >= n {
printf!("There are {} repetition of '{}'", repeat, cur_ch);
}
cur_ch = ch;
repeat = 1;
}
}
if repeat >= n {
printf!("There are {} repetition of '{}'", repeat, cur_ch);
}
它可以工作,但是有没有更好的方法通过链接 iter 方法来做到这一点?
最佳答案
这是一个使用 scan
的解决方案和filter_map
:
fn main() {
let s = "112225322555";
let n = 2;
let i = s
.chars()
.map(|v| Some(v))
.chain(std::iter::once(None))
.scan((0, None), |(count, ch), v| match ch {
Some(c) if *c == v => {
*count += 1;
Some((None, *count))
}
_ => Some((ch.replace(v), std::mem::replace(count, 1))),
})
.filter_map(|(ch, count)| match ch {
Some(Some(ch)) if count >= n => Some((ch, count)),
_ => None,
});
for (ch, num) in i {
println!("There are {} repititions of {}", num, ch);
}
}
第一步是使用scan
计算相邻字符的数量。 scan
的第一个参数是一个状态变量,它会传递给作为第二个参数传递的闭包的每次调用。在本例中,状态变量是一个包含当前字符及其出现次数的元组。
注意:
我们需要将迭代扩展到我们正在分析的字符串末尾之外(否则我们会错过字符串末尾包含一系列符合条件的字符的情况)。我们通过将迭代映射到
Option<char>
来做到这一点然后链接到单个None
。这比特殊大小写字符(例如\0
)要好。 ,这样我们就可以数\0
字符。出于同样的原因,我们使用
Option<char>
作为状态元组中的当前字符。scan
的返回值是(Option<Option<char>>, i32)
上的迭代器。元组中的第一个值将是None
对于迭代器中的每个重复字符,而在字符更改的每个边界处,它将是Some(Some(char))
我们使用
replace
返回当前字符和计数,同时将状态元组设置为新值
最后一步是使用filter_map
至:
删除
(None, i32)
变体,表示传入字符没有变化过滤掉计数未达到限制的情况
n
.
关于rust - 检测按顺序发生的字符串切片的重复元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63327968/