2

I have a vector and trying to create a new vector by filtering. It does not work and I don't know why:

fn example(data: Vec<f64>, missing_value: f64) {
    let dude = data
        .iter()
        .filter(|&x| *x != missing_value)
        .collect::<Vec<f64>>();
}
error[E0277]: a collection of type `std::vec::Vec<f64>` cannot be built from an iterator over elements of type `&f64`
 --> src/lib.rs:5:10
  |
5 |         .collect::<Vec<f64>>();
  |          ^^^^^^^ a collection of type `std::vec::Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
  |
  = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec<f64>`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Tampa
  • 75,446
  • 119
  • 278
  • 425

1 Answers1

9

There is a single implementation of FromIterator for Vec, and this implementation collects values of T from the same type T, i.e., it is not possible to convert T into an arbitrary type U and collect its elements at the same time.

In your case, you want to collect an iterator of &f64 into a vector of f64, therefore, you need to convert by cloning/copying and then collect.

self.data.iter().filter(|&&x| x != self.missing_value).cloned().collect::<Vec<f64>>();

If you have ownership of the vector, it is possible to iterate over f64 instead of &f64 by using into_iter.

self.data.into_iter().filter(|&x| x != self.missing_value).collect::<Vec<f64>>();
Caio
  • 3,178
  • 6
  • 37
  • 52
  • 1
    https://play.integer32.com/?version=stable&mode=debug&edition=2018&gist=f9906ee9a4373bda1e47d82b755d41ad ? – Stargateur Jan 20 '19 at 13:09
  • 2
    You should use `retain` instead of `into_iter` + `filter` + `collect` if you are okay with consuming the `Vec`. Know your standard library! – trent Jan 20 '19 at 13:57
  • Also, I'd put `cloned()` before `filter`, and avoid the double-borrow, but maybe that's just me. – trent Jan 20 '19 at 14:00