How do I convert a list of Option<T> to a list of T when T cannot be copied?
In Rust, when you need a value, you generally want to move the elements or clone them.
Since move is more general, here it is, only two changes are necessary:
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 out, filter_map
is specialized to filter out None
already:
let nums: Vec<Uncopyable> = num_opts
.into_iter()
// ^~~~~~~~~~~~-------- Consume vector, and iterate by value
.filter_map(|x| x)
// ^~~----- Take by value
.collect();
And then it works (consuming num_opts
).
You don't need to copy the Uncopyable
at all, if you are OK with using a Vec
of references into the original Vec
:
let nums: Vec<&Uncopyable> = num_opts.iter().filter_map(|x| x.as_ref()).collect();
// ^ notice the & before Uncopyable?
This may not do the trick for you if you have to work with an API that requires &[Uncopyable]
. In that case, use Matthieu M.'s solution which can be reduced to:
let nums: Vec<Uncopyable> = num_opts.into_iter().filter_map(|x| x).collect();