我如何取一个Vec<Option<T>>,其中T不能被复制,然后打开所有Some个值?

我在map步中遇到了一个错误.我很高兴能转移原始名单的所有权,并"扔掉"None.

#[derive(Debug)]
struct Uncopyable {
    val: u64,
}

fn main() {
    let num_opts: Vec<Option<Uncopyable>> = vec![
        Some(Uncopyable { val: 1 }),
        Some(Uncopyable { val: 2 }),
        None,
        Some(Uncopyable { val: 4 }),
    ];

    let nums: Vec<Uncopyable> = num_opts
        .iter()
        .filter(|x| x.is_some())
        .map(|&x| x.unwrap())
        .collect();
    println!("nums: {:?}", nums);
}

Playground

这就产生了错误

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:17:15
   |
17 |         .map(|&x| x.unwrap())
   |               ^-
   |               ||
   |               |hint: to prevent move, use `ref x` or `ref mut x`
   |               cannot move out of borrowed content

推荐答案

在Rust中,当需要一个值时,通常需要将元素设置为moveclone.

由于move更为通用,这里只需要两个更改:

let nums: Vec<Uncopyable> = num_opts
    .into_iter()
//  ^~~~~~~~~~~~-------------- Consume vector, and iterate by value
    .filter(|x| x.is_some())
    .map(|x| x.unwrap())
//       ^~~------------------ Take by value
    .collect();

As llogiq points outfilter_map专门用于过滤掉None:

let nums: Vec<Uncopyable> = num_opts
    .into_iter()
//  ^~~~~~~~~~~~-------- Consume vector, and iterate by value
    .filter_map(|x| x)
//              ^~~----- Take by value
    .collect();

然后它开始工作(消耗num_opts).

正如@nirvana-msu所指出的,在 rust 中添加了1.33 std::convert::identity,可以代替|x| x使用.从文件中:

let filtered = iter.filter_map(identity).collect::<Vec<_>>();

Rust相关问答推荐

基于对vec值的引用从该值中删除该值

程序退出后只写入指定管道的数据

如何访问Rust存储值的内存地址

通过解引用将值移出Box(以及它被脱糖到什么地方)?

S,一般性状和联想型性状有什么不同?

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

完全匹配包含大小写的整数范围(&Q;)

循环访问枚举中的不同集合

在macro_rule中拆分模块和函数名

Rust 中的静态引用

如何在 Rust 中编写一个通用方法,它可以接受任何可以转换为另一个值的值?

Boxing 如何将数据从堆栈移动到堆?

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

内部值发生变化时 Rc 的行为

&str 的编译时拆分是否可能?

为什么 Rust 允许写入不可变的 RwLock?

If let expression within .iter().any

您如何使用枚举反序列化字符串,其中任何其他值反序列化为新类型变体同时保留字符串?

Rust:如果我知道只有一个实例,那么将可变borrow 转换为指针并返回(以安抚borrow 判断器)是否安全?

为什么我不能为 Display+Debug 的泛型类型实现 std::error::Error 但有一个不是泛型参数的类型?