当无法复制 T 时,如何将 Option<T> 列表转换为 T 列表?
How do I convert a list of Option<T> to a list of T when T cannot be copied?
我如何获取 Vec<Option<T>>
,其中 T
无法复制,并展开所有 Some
值?
我运行在map
这一步出错了。我很高兴移动原始列表的所有权和 "throw away" 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
你根本不需要复制 Uncopyable
,如果你可以使用 Vec
的引用到原始 Vec
:
let nums: Vec<&Uncopyable> = num_opts.iter().filter_map(|x| x.as_ref()).collect();
// ^ notice the & before Uncopyable?
如果您必须使用需要 &[Uncopyable]
的 API,这可能对您不起作用。在这种情况下,使用 可以简化为:
let nums: Vec<Uncopyable> = num_opts.into_iter().filter_map(|x| x).collect();
在 Rust 中,当你需要一个值时,你通常希望移动 元素或 克隆 它们。
由于move比较通用,所以这里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();
作为,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
)。
正如 @nirvana-msu, in Rust 1.33 std::convert::identity
所指出的那样,添加了可以用来代替 |x| x
的内容。来自文档:
let filtered = iter.filter_map(identity).collect::<Vec<_>>();
我如何获取 Vec<Option<T>>
,其中 T
无法复制,并展开所有 Some
值?
我运行在map
这一步出错了。我很高兴移动原始列表的所有权和 "throw away" 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
你根本不需要复制 Uncopyable
,如果你可以使用 Vec
的引用到原始 Vec
:
let nums: Vec<&Uncopyable> = num_opts.iter().filter_map(|x| x.as_ref()).collect();
// ^ notice the & before Uncopyable?
如果您必须使用需要 &[Uncopyable]
的 API,这可能对您不起作用。在这种情况下,使用
let nums: Vec<Uncopyable> = num_opts.into_iter().filter_map(|x| x).collect();
在 Rust 中,当你需要一个值时,你通常希望移动 元素或 克隆 它们。
由于move比较通用,所以这里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();
作为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
)。
正如 @nirvana-msu, in Rust 1.33 std::convert::identity
所指出的那样,添加了可以用来代替 |x| x
的内容。来自文档:
let filtered = iter.filter_map(identity).collect::<Vec<_>>();