Rya*_*729 6 iteration iterator rust
鉴于此定义foo:
let foo = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
Run Code Online (Sandbox Code Playgroud)
我希望能够编写这样的代码:
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter().map(|x| x * 2)
} else {
std::iter::empty()
})
.collect();
Run Code Online (Sandbox Code Playgroud)
但是这引发了关于if和else子句具有不兼容类型的错误.我尝试map暂时删除,我尝试在闭包外定义一个空向量,然后返回迭代器,如下所示:
let empty = vec![];
let result: Vec<_> = foo.iter()
.enumerate()
.flat_map(|(i, row)| if i % 2 == 0 {
row.iter() //.map(|x| x * 2)
} else {
empty.iter()
})
.collect();
Run Code Online (Sandbox Code Playgroud)
这似乎有点傻,但它编译.如果我试图取消注释map然后它仍然抱怨if和else子句具有不兼容的类型.以下是错误消息的一部分:
error[E0308]: if and else have incompatible types
--> src/main.rs:6:30
|
6 | .flat_map(|(i, row)| if i % 2 == 0 {
| ______________________________^
7 | | row.iter().map(|x| x * 2)
8 | | } else {
9 | | std::iter::empty()
10 | | })
| |_________^ expected struct `std::iter::Map`, found struct `std::iter::Empty`
|
= note: expected type `std::iter::Map<std::slice::Iter<'_, {integer}>, [closure@src/main.rs:7:28: 7:37]>`
found type `std::iter::Empty<_>`
Run Code Online (Sandbox Code Playgroud)
我知道我可以用一些嵌套for循环编写一些可以做我想要的东西,但是我想知道是否有一种简洁的方法来使用迭代器来编写它.
由于Rust是静态类型的,并且迭代器链中的每个步骤都将结果更改为一个新类型,该新类型会夹带先前的类型(除非使用盒装特征对象),因此您必须以两种类型都覆盖相同分支的方式编写它。
传递单一类型的条件空度的一种方法是TakeWhile迭代器实现。
.flat_map(|(i, row)| {
let iter = row.iter().map(|x| x * 2);
let take = i % 2 == 0;
iter.take_while(|_| take)
})
Run Code Online (Sandbox Code Playgroud)
如果您不介意忽略输入迭代器foo可以包含多个usize元素的Take极端情况,则也可以使用0或usize :: MAX代替。它具有提供size_hint()比更好的优势TakeWhile。
在您的特定示例中,您可以filter在调用之前用于删除不需要的元素flat_map:
let result: Vec<_> = foo.iter()
.enumerate()
.filter(|&(i, _)| i % 2 == 0)
.flat_map(|(_, row)| row.iter().map(|x| x * 2))
.collect();
Run Code Online (Sandbox Code Playgroud)
如果你想用用它map来代替flat_map,你可以调用结合起来,filter并map通过使用filter_map这需要一个函数返回一个Option,只保留那些元素Some(thing)。
| 归档时间: |
|
| 查看次数: |
746 次 |
| 最近记录: |