在Rust中处理flat_map中可能的单个元素

问题描述 投票:0回答:1

是否可以在Rust的flat_map中处理不同数量的元素?

根据情况,我需要映射单个enum元素或enum元素的向量。

我尝试使用std::iter::once,但由于onceVec::iter是不同的类型,因此无法从相同的if条件返回,因此无法正常工作。

enum Enum {
    Ident(String),
    Val(i32)
}

fn main() {
    let my_vec = vec![1, 2, 3];
    let condition = true; // Any condition

    my_vec.iter()
          .flat_map(|x| {
              if condition {
                  std::iter::once(Enum::Ident("id".to_string())).into_iter() /* single Enum element */
              } else {
                  vec![Enum::Val(1), Enum::Val(2)].iter() /* vector of Enum elements */
              }
          })
          .collect::<Vec<Enum>>()
}
   |
12 | /               if condition {
13 | |                   std::iter::once(Enum::Ident("id".to_string())).into_iter() /* single Enum element */
   | |                   ---------------------------------------------------------- expected because of this
14 | |               } else {
15 | |                   vec![Enum::Val(1), Enum::Val(2)].iter() /* vector of Enum elements */
   | |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::iter::Once`, found struct `std::slice::Iter`
16 | |               }
   | |_______________- if and else have incompatible types
   |
   = note: expected type `std::iter::Once<Enum>`
              found type `std::slice::Iter<'_, Enum>`
enums rust
1个回答
1
投票

显而易见的解决方案是在两种情况下都使用向量:

my_vec
    .iter()
    .flat_map(|_| {
        if condition {
            vec![Enum::Ident("id".to_string())].into_iter()
        } else {
            vec![Enum::Val(1), Enum::Val(2)].into_iter()
        }
    })
    .collect::<Vec<Enum>>();

这将导致对单元素向量进行额外分配,但这是一个简单易读的解决方案。如果要避免这种开销,一种选择是使用either条板箱:

use either::{Left, Right};

enum Enum {
    Ident(String),
    Val(i32),
}

fn main() {
    let my_vec = vec![1, 2, 3];
    let _ = my_vec
        .iter()
        .flat_map(|&x| {
            if x > 1 {
                Left(std::iter::once(Enum::Ident("id".to_string())))
            } else {
                Right(vec![Enum::Val(1), Enum::Val(2)].into_iter())
            }
        })
        .collect::<Vec<Enum>>();
}

该板条箱定义了带有变体EitherLeft的通用枚举Right。如果双方的类型都支持迭代,则枚举还可以通过分派给相应的基础迭代器类型来支持迭代。

© www.soinside.com 2019 - 2024. All rights reserved.