Is there a nicer alternative to ".map(|x| *x)" before ".collect()"?

Viewed 183

In the following snippet:

let b: Vec<usize> = a.iter().filter(|x| **x > 5).map(|x| *x).collect();

Is there a nicer way to make b be a vector of values rather than references? (instead of .map(|x| *x))

Is there something like:

fn iter_values<T : Copy>(c: &Vec<T>) -> std::iter::Map<std::slice::Iter<T>, fn(&T) -> T> {
    c.iter().map(|x| *x)
}

That can be used like so:

let b: Vec<usize> = iter_values(&a).filter(|x| *x > 5).collect();
2 Answers

Use .copied:

let b: Vec<usize> = a.iter().copied().filter(|x| *x > 5).collect();

Alternatively you can use .cloned which works for any type that implements Clone, but beware that this might induce a non-trivial cost to turn references into objects by cloning them.

As an alternative to using copied() or cloned(), you may be able to consume the source container by using into_iter() instead of iter():

let b: Vec<usize> = a.into_iter().filter(|x| *x > 5).collect();

You can use this if you don't need the original container after this point in the code.

Related