如何避免此程序的 for 循环和 let 语句

Lyn*_* Wu 2 rust

在 Rust 中,如何避免编写 for 循环和 let 语句?该程序用于记录字符串出现在文本的哪一行以及出现在该行的位置。

我知道我可以使用迭代器和映射来消除它们,但是我刚刚接触了 Rust,我不知道如何编写它。

pub struct L{
    x: usize,
    y: usize,
}
pub fn foo (text: &str, string: &str)->Vec<L> {
    let mut r= Vec::new();
    let mut x=0;
    for line in text.lines(){
        for (y, _) in line.match_indices(string){
            r.push(L{
                    x : x,
                    y: y, })
        }
        x+=1;
    }
    r
}
Run Code Online (Sandbox Code Playgroud)

kmd*_*eko 7

这是等效的使用迭代器:

pub fn foo(text: &str, string: &str) -> Vec<L> {
    text.lines()
        .enumerate()
        .flat_map(|(x, line)| {
            line.match_indices(string).map(move |(y, _)| { L { x, y } })
        })
        .collect()
}
Run Code Online (Sandbox Code Playgroud)

线的分解线:

.enumerate()
Run Code Online (Sandbox Code Playgroud)

enumerate用于将 的迭代器T转换为 的迭代器(usize, T),基本上是用索引压缩原始值。您这样做是因为您正在使用 跟踪行号x

.flat_map(|(x, line)| { ... })
Run Code Online (Sandbox Code Playgroud)

flat_map 用于允许迭代器中的每个值返回其自己的迭代器,然后将其值展平为一个流。

line.match_indices(string).map(move |(y, _)| { L { x, y } })
Run Code Online (Sandbox Code Playgroud)

这里我们只是使用map采取xy创造的Lmove被使用是因为否则x会为闭包借用,但迭代器和闭包返回给flat_map闭包,存活时间比x. 这move只是复制,x所以这不是问题。

.collect()
Run Code Online (Sandbox Code Playgroud)

collect用于将迭代器转换为可以通过实现从迭代器生成的东西FromIterator,通常是像Vec. 这也是通过知道我们正在返回 a 来使用类型推断Vec<L>,它知道收集到 a 中Vec<L>


您可以在 上验证等效性Rust Playground