0

我有一个称为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 专业人士会以相同的方式编写此代码,还是有更好的方式?

4

0 回答 0