Reputation: 111
I want to be able to create a new vector c: Vec<T>
from a: Vec<T>
and b: T
where c
is equal to b
appended to a
, without using mutables. Say I have this code-
fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
return Vec::<T>::new(a, b);
}
I am aware this does not work, because Vec::new()
has no input parameters. What I am wondering is if there is an function or macro in std::vec
that can initialize a vector from another vector and a set of additional values to append onto the vector. I know a function can be created very easily to do this, I am just wondering if functionality exists in the standard library to work with vectors without them being mutable in the first place.
Upvotes: 2
Views: 1289
Reputation: 155046
Note that you can use the tap
crate to push b
to a
in an expression that evaluates to a
:
use tap::Tap;
fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
a.tap_mut(|a| a.push(b))
}
This combines the performance benefits of push()
(in comparison to building a brand new vector) with the elegance of having a short expression.
Upvotes: 2
Reputation: 97
Vec::from_iter
should work if you're willing to use iterators.
pub fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
return Vec::from_iter(a.into_iter().chain(std::iter::once(b)));
}
Edit(s): Also as far as I have seen: the most common way to work with vectors, slices, and arrays is through the use of the Iterator
trait and the functionality it provides.
Also on the topic of speed: the above approach is slightly faster if you avoid cloning. On my computer iterators take about 1.571µs per call whereas cloning and pushing to a vector took 1.580µs per call. (Tested by running the functions 300 000 times on a debug build.)
Upvotes: 0
Reputation: 3728
The universal form of the inefficient solution should look like this:
fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
Vec::from_iter(a.into_iter().chain(std::iter::once(b)))
}
…but its strongly recommended to use push
:
fn concat_vec<T: std::clone::Clone>(a: Vec<T>, b: T) -> Vec<T> {
let mut rslt = a.to_vec();
rslt.push(b);
rslt
}
Upvotes: 0