Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to somehow cast Vec<Option<Value>> into Vec<Value> after filtering out None elements in Rust? [duplicate]

I want some way to have such a cast when writing code like this:

struct Value;

fn remove_missed(uncertain_vector: Vec<Option<Value>>) -> Vec<Value> {
    uncertain_vector
        .into_iter()
        .filter(|element| match element {
            Some(val) => true,
            None => false,
        })
        .collect()
}

How can I achieve this? I believe that the type implication mechanism is not smart enough to determine that the resulting collection will contain only Option<Value> where all such objects are the same in terms of their type (Value).

The compiler answers my question partially:

error[E0277]: a collection of type `std::vec::Vec<Value>` cannot be built from an iterator over elements of type `std::option::Option<Value>`
  --> src/lib.rs:10:10
   |
10 |         .collect()
   |          ^^^^^^^ a collection of type `std::vec::Vec<Value>` cannot be built from `std::iter::Iterator<Item=std::option::Option<Value>>`
   |
   = help: the trait `std::iter::FromIterator<std::option::Option<Value>>` is not implemented for `std::vec::Vec<Value>`
like image 723
Vladimir Ignatyev Avatar asked Dec 10 '22 03:12

Vladimir Ignatyev


1 Answers

You can use Iterator::flatten which creates "an iterator that flattens nested structure" – in this case, pulls out Some from Option.

let v = vec![None, None, Some(1), Some(2), None, Some(3)];
let filtered: Vec<_> = v.into_iter().flatten().collect();

Or Iterator::filter_map to filter and map the element in one go – with an equal result.

let filtered: Vec<_> = v.into_iter().filter_map(|e| e).collect();

Playground

like image 110
belst Avatar answered Jun 08 '23 22:06

belst