rust - Rust 中枚举的展平向量
问题描述
我正在尝试Enum
在 Rust 中展平一个向量,但我遇到了一些问题:
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);
}
这基本上与您尝试做的事情相同,但以一种会成功的方式。以下是我更改的部分,按照它们在代码中出现的顺序:
我用
.flat_map()
而不是.map()
.flat_map
接受一个函数,该函数返回一个迭代器并生成该迭代器的元素(“展平”),而.map()
刚刚给出了迭代器。我
&
在match
图案中使用过。这是因为,由于您.iter()
在向量上使用(这适合您的要求“<code>vf 必须仍然有效”),您有对枚举的引用,并且对枚举的引用的模式匹配通常会为您提供引用到它的元素,但我们几乎可以肯定想要i32
按值处理 s 。我还可以做其他几件事,例如*
在值上使用取消引用运算符,但这是简洁而整洁的。你尝试了
.into_iter()
一个数组。不幸的是,在当前的 Rust 中,这并不能满足您的要求,并且您实际上无法返回该迭代器,原因有些尴尬(这将在即将到来的 Rust 版本中修复)。然后,如果它确实意味着你想要的,那么你会得到一个错误,因为这两个match
臂的类型不相等——一个是迭代器 over[i32; 1]
,另一个是迭代器 over[i32; 2]
。相反,您需要构建两个可能的迭代器,它们显然属于同一类型。有很多方法可以做到这一点,我选择的方法是使用
Iterator::chain
combineonce(i)
,一个返回单个元素的迭代器i
,以及一个包含第二个元素(如果存在Option<i32>
)的(实现) 。IntoIterator
j
请注意,在第一
match
臂中,我写了看似无用的表达式.chain(None)
;这是为了使两个手臂具有相同的类型。编写相同内容的另一种方法是: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>>
——您不需要确切地知道这一点,只需注意必须有一个类型可以同时处理 theA(i)
和B(i, j)
case。
推荐阅读
- python - 无论如何我可以从python中的MIME对象获取用户名吗?
- node.js - 对Node中数组中的每个对象调用一个函数
- javascript - 使用 R 使用表单和 JS 抓取网站
- c# - 使用 Json.Net 的 JObject.FromObject 方法进行序列化时,我可以使用自定义 ContractResolver 吗?
- jquery - 在html中输出一个jquery变量?
- xml - XML 解析错误:我不能在 DynamicPage 中嵌套 RowActionItem 吗?
- python - 绕过Django中多对多关系的唯一约束的最佳方法?
- javascript - 如何使当前单击的选项卡的内容始终显示在不同的容器中?
- sql - 舍入时间到精确小时 SQL Server
- php - symfony 实体的 PHP 7 类型声明