gpt4 book ai didi

rust - Rust 中枚举的展平向量

转载 作者:行者123 更新时间:2023-12-05 09:33:22 29 4
gpt4 key购买 nike

我试图在 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com