【问题标题】:How to convert a vector of options to a simple vector in Rust?如何将选项向量转换为 Rust 中的简单向量?
【发布时间】:2021-07-18 21:58:33
【问题描述】:

假设我有一个Vec,其中包含一个名为“Dummy”的结构的可选框。

struct Dummy {
    foo: i32
}

fn main() {
    let a = Box::new(Dummy {foo: 42});
    let b = Box::new(Dummy {foo: 69});
    let c = Box::new(Dummy {foo: 420});

    let bar = vec![Some(a), None, Some(b), None, Some(c)];

    // This works, but it's a lot of calls for a single task.
    let only_elements: Vec<&Box<Dummy>> = bar.iter()
        .filter(|&el| el.is_some())
        .map(|el| el.as_ref().unwrap())
        .collect();

    for el in only_elements {
        println!("{}", el.foo);
    }
}

如何以更漂亮的方式将这个Vec 选项转换为简单的Vec 引用? 我写了我能想到的唯一方法,但是对于我看来微不足道的事情,它看起来有点乏味。

【问题讨论】:

标签: vector rust optional


【解决方案1】:

您可以使用filter_map。它会从您拥有的内容中删除至少一行。您还可以在collect::&lt;Vec&lt;_&gt;&gt; 中使用turbofish 和下划线来指定类型,这样您就无需显式声明类型以防更改映射。

let only_elements = bar.iter()
        .filter_map(Option::as_ref)
        .collect::<Vec<_>>();

您可以从here 阅读有关filter_map 的更多信息。


正如@Masklinn 和here 所提到的,Option 实现了IntoIterator,因此您也可以将flatten 用于Option,就像用于Result 一样。

let only_elements = bar.iter().flatten().collect::<Vec<_>>();

【讨论】:

  • 我们也可以稍微不同地写这个。由于在原始代码中指定了only_elements 的类型,我们可以在这里省略,我们可以使用Option::as_ref - 它给出let only_elements: Vec&lt;_&gt; = bar.iter().filter_map(Option::as_ref).collect(); (其中 rustfmt 很乐意保持一行)
  • ^已更新以包含您的部分建议。我更喜欢将Vec&lt;_&gt; 留给collect,因为我的编辑器使用自动显示类型的rust-analyzer。
  • @ToninGuy3n 因为Option 实现了IntoIteratorflatten 实际上会完成您正在使用filter_map(Option::as_ref) 的工作。
猜你喜欢
  • 1970-01-01
  • 2016-10-29
  • 2018-09-06
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多