如何使用Vec<Option<T>>
,无法复制T
并解开所有Some
值?
我在map
步骤中遇到错误。我很乐意移动原始列表的所有权并且&#34;扔掉&#34; None
s。
#[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);
}
哪个给出了错误
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
答案 0 :(得分:5)
在Rust中,当您需要一个值时,通常需要移动元素或克隆它们。
由于移动更为通用,此处为it is,因此只需进行两项更改:
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();
作为llogiq points out,filter_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
)。
答案 1 :(得分:3)
如果您可以使用原始Uncopyable
Vec
的{{1}}个引用,则无需复制Vec
:
let nums: Vec<&Uncopyable> = num_opts.iter().filter_map(|x| x.as_ref()).collect();
// ^ notice the & before Uncopyable?
如果您必须使用需要&[Uncopyable]
的API,这可能无法解决问题。在这种情况下,请使用Matthieu M.'s solution,可以缩减为:
let nums: Vec<Uncopyable> = num_opts.into_iter().filter_map(|x| x).collect();