rust - Rust 中枚举的展平向量

标签 rust

我试图在 Rust 中展平 Enum 的向量,但我遇到了一些问题:

enum Foo {
    A(i32),
    B(i32, i32),
}

fn main() {
    let vf = vec![Foo::A(1), Foo::A(2), Foo::B(3, 4)];

    let vi: Vec<i32> = vf
        .iter()
        .map(|f| match f {
            Foo::A(i) => [i].into_iter(),
            Foo::B(i, j) => [i, j].into_iter(),
        })
        .collect(); // this does not compile

    // I want vi = [1, 2, 3, 4]. vf must still be valid
}

我可以只使用常规的 for 循环并将元素插入现有的向量中,但这并不有趣。我想知道是否有更惯用的 Rust 方法。

最佳答案

这是一种生成迭代器的方法(而不是像基于 fold() 的解决方案那样必须是向量)。

use std::iter::once;

enum Foo {
    A(i32),
    B(i32, i32),
}

fn main() {
    let vf = vec![Foo::A(1), Foo::A(2), Foo::B(3, 4)];

    let vi: Vec<i32> = vf
        .iter()
        .flat_map(|f| {
            match f {
                &Foo::A(i) => once(i).chain(None),
                &Foo::B(i, j) => once(i).chain(Some(j)),
            }
        })
        .collect();

    dbg!(vi);
}

这基本上与您尝试的相同,但以一种会成功的方式。以下是我更改的部分,按照它们在代码中出现的顺序排列:

  1. 我使用了 .flat_map() 而不是 .map() . flat_map接受一个函数,该函数返回一个迭代器 并生成该迭代器的元素(“展平”),而.map()只会给出迭代器。

  2. 我使用了 &match模式。这是因为,因为您正在使用 .iter()在向量上(这适合您的要求“vf 必须仍然有效”),您有对枚举的引用,并且对枚举引用的模式匹配通常会给您它的元素的引用,但我们几乎肯定想要处理 i32 s 按值代替。我还可以做其他几件事,例如使用 *取而代之的是在值上取消引用运算符,但这样简洁明了。

  3. 您尝试了 .into_iter()数组。不幸的是,在当前的 Rust 中,这并没有做你想做的事情,你实际上不能返回那个迭代器,因为有些尴尬的原因 ( which will be fixed in an upcoming Rust version )。然后,如果它确实是你想要的,那么你会得到一个错误,因为两个 match arms 有不同的类型——一个是 [i32; 1] 上的迭代器另一个是 [i32; 2] 上的迭代器.

    相反,您需要构建两个明显相同 类型的迭代器。有很多方法可以做到这一点,我选择的方法是使用 Iterator::chain 结合 once(i) ,一个返回单个元素的迭代器 i , 与 Option<i32> (实现 IntoIterator )包含第二个元素 j 如果存在

    请注意,在第一个 match arm 我写了看似没用的表达式 .chain(None) ;这是为了使两个 ARM 具有相同的类型。另一种编写相同内容的方法可以说更清晰,因为它不会重复必须相同的代码,它是:

    let (i, opt_j) = match f {
        &Foo::A(i) => (i, None),
        &Foo::B(i, j) => (i, Some(j)),
    };
    once(i).chain(opt_j)
    

    无论哪种情况,迭代器的类型都是 std::iter::Chain<std::iter::Once<i32>, std::option::IntoIter<i32>> — 您不需要确切地知道这一点,只需注意必须 一个类型来处理 A(i)B(i, j)例。

关于rust - Rust 中枚举的展平向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67346301/

相关文章:

rust - SFML 中的生命周期说明符和泛型

rust - 在procmacro中的所有字段和子字段上递归调用函数

rust - Rust:Fn成员签名中使用的Struct泛型类型参数需要命名生命周期

rust - 返回对特征而不是结构的引用

rust - 一次不能多次借用 `*self` 作为可变的

arrays - 查找数组组合的中点

Rust cargo.toml 为 C 链接器和编译器指定自定义路径

rust - 我怎样才能拥有一个仅用于其内部常量的结构?

rust - 构造一个结构体,其中包含来自 'from_iter' 的 i32 通用迭代器?

testing - 如何测试 Rust 程序传递给另一个程序的参数?