有条件地从flat_map返回空迭代器

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循环编写一些可以做我想要的东西,但是我想知道是否有一种简洁的方法来使用迭代器来编写它.

the*_*472 5

由于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


Jmb*_*Jmb 5

在您的特定示例中,您可以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,你可以调用结合起来,filtermap通过使用filter_map这需要一个函数返回一个Option,只保留那些元素Some(thing)