Derefence a vector of references in Rust

276 Views Asked by At

If I have a vector of references, I can do this:

references.into_iter().map(|x| *x).collect::<Vec<_>>();

Is there a short-hand that does this? This would be easy to answer with hoogle-like search engine but I can't find one for Rust.

Relatedly, I'd be also curious if there is a shorthand for the opposite operation:

objects.iter().collect::<Vec<_>>()
3

There are 3 best solutions below

0
On BEST ANSWER

There's probably no operation exactly like the one you want. You can clone() the vector, but that will just give you another vector with the same references. If you want to transform the vector elements, you're supposed to do that with the iterator interface because, after all, you might not want to save the results into a vector. And if you do want the results in a vector - well, that's what collect() is for.

Having said the above, here are some ways to make it shorter:

  • You can replace map(|x| *x) with copied().
  • If you're returning the vector from the function, you don't need the explicit ::<Vec<_>> "turbofish" because the function will have the return type spelled out, and Rust will be able to infer it.
  • You don't even need explicit return if it's the last expression in your function.

Combining the above, you can replace return references.into_iter().map(|x| *x).collect::<Vec<_>>(); with references.into_iter().copied().collect(), which is visibly shorter, though perhaps not exactly what you were after.

0
On

The itertools crate has a method collect_vec that allows you to get rid of the turbofish syntax:

use itertools::Itertools;

references.into_iter().map(|x| *x).collect_vec()

With type inference, it is sometimes possible to use collect directly as well. Admittedly, the improvement is minimal.

0
On

You can create a trait that provides a convenience method on Vecs which performs this function for you:

trait CloneRefs<T> {
    fn clone_refs(&self) -> Vec<T>;
}

impl<T> CloneRefs<T> for [&T] where T: Clone {
    fn clone_refs(&self) -> Vec<T> {
        self.into_iter().map(|&x| x.clone()).collect()
    }
}

fn main() {
    let refs = vec![&1, &2, &3];
    let owned = refs.clone_refs(); // compiles
}

playground

Note: since the Copy trait requires Clone the above will work for all Clone and Copy types.