在 Rust 中,如何避免编写 for 循环和 let 语句?该程序用于记录该字符串出现在文本的哪一行以及出现在该行的位置。
我知道我可以用迭代器和map来消除它们,但是我刚接触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
}
最佳答案
这等效于使用迭代器:
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()
}
逐行分解:
.enumerate()
enumerate
用于转换 T
的迭代器进入 (usize, T)
的迭代器,基本上用索引压缩原始值。您这样做是因为您正在使用 x
跟踪行号。 .
.flat_map(|(x, line)| { ... })
flat_map
用于允许迭代器中的每个值返回其自己的迭代器,其值然后被展平到一个流中。
line.match_indices(string).map(move |(y, _)| { L { x, y } })
这里我们只是使用 map
采取x
和 y
并创建一个 L
. move
被使用是因为否则 x
将为闭包借用,但迭代器和闭包将返回给 flat_map
关闭,生命周期超过x
. move
只是复制 x
所以这不是问题。
.collect()
collect
用于将迭代器转换为可以通过实现 FromIterator
从迭代器生成的东西, 通常是像 Vec
这样的集合.这也是通过知道我们返回一个 Vec<L>
来使用类型推断。 , 它知道收集到 Vec<L>
.
您可以在 Rust Playground
上验证等价性.
关于rust - 如何避免此程序的 for 循环和 let 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64614968/