我有一个称为Finder
在字符串列表中搜索单词的结构:
fn main() {
let lines = vec![
"The first line.",
"And the second one.",
"The very last line.",
];
let word = "the";
let iter = lines.iter().map(|x| String::from(*x));
let finder = Finder::new();
for matched in finder.find(iter, word) {
println!("{:?}", matched);
}
}
pub struct Finder {
ignore_case: bool,
}
#[derive(Debug)]
pub struct Match {
line_no: usize,
offset: usize,
line: String,
}
impl Finder {
pub fn new() -> Finder {
Finder { ignore_case: true }
}
pub fn find<'a, I: 'a>(
&'a self,
lines: I,
word: &'a str,
) -> impl std::iter::Iterator<Item = Match> + 'a
where
I: std::iter::Iterator<Item = String>,
{
let word = String::from(word);
lines
.enumerate()
.filter_map(move |(i, line)| match self.find_word(&line, &word) {
Some(index) => Some(Match {
line_no: i,
offset: index,
line: String::from(line),
}),
None => None,
})
}
fn find_word(&self, line: &str, word: &str) -> Option<usize> {
if self.ignore_case {
line.to_lowercase().find(&word.to_lowercase())
} else {
line.find(word)
}
}
}
我想说这个实现比它应该的要间接得多,但我想更好地探索可用语言的特性。
该方法find
接受一个迭代器,并返回产生Match
结果的迭代器。代码按预期工作,但感觉相当复杂!该find
方法的签名包括模板、生命周期和其他对于新手来说看起来很棘手的东西。
有没有更好的方法从方法返回迭代器?我可以使用简单的函数和结构来实现相同的逻辑,或者只调用filter_map
向量,但我的目标是更好地掌握语言的功能。
是否可以从方法返回迭代器,但具有更简单的方法签名,或者在这种情况下是否期望具有这样的“详细”签名?
这段代码是在编译器的帮助下编写的,也就是说,我一个接一个地修复错误,直到它起作用。Rust 专业人士会以相同的方式编写此代码,还是有更好的方式?