To create a new vector with the contents of other vectors, I'm currently doing this:
fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
let abc = Vec<i32> = {
let mut tmp = Vec::with_capacity(a.len(), b.len(), c.len());
tmp.extend(a);
tmp.extend(b);
tmp.extend(c);
tmp
};
// ...
}
Is there a more straightforward / elegant way to do this?
We can combine vectors by adding them, the sum of two vectors is called the resultant. In order to add two vectors, we add the corresponding components.
To concatenate a vector or multiple vectors in R use c() function. This c() function is used to combine the objects by taking two or multiple vectors as input and returning the vector with the combined elements from all vectors.
No, vector addition does not apply to any two vectors. Two vectors are added only when they are of the same type and nature. For instance, two velocity vectors can be added, but one velocity vector and one force vector cannot be added.
This is called a linear combination. We call the set of all the vectors that are reachable by our set of vectors the span of those vectors.
There is a concat
method that can be used for this, however the values need to be slices, or borrowable to slices, not &Vec<_>
as given in the question.
An example, similar to the question:
fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
let abc = Vec<i32> = [a.as_slice(), b.as_slice(), c.as_slice()].concat();
// ...
}
However, as @mindTree notes, using &[i32]
type arguments is more idiomatic and removes the need for conversion. eg:
fn func(a: &[i32], b: &[i32], c: &[i32]) {
let abc = Vec<i32> = [a, b, c].concat();
// ...
}
SliceConcatExt::concat
is a more general version of your function and can join multiple slices to a Vec. It will sum the sizes each slice to pre-allocate a Vec of the right capacity, then extend repeatedly.
fn concat(&self) -> Vec<T> {
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
let mut result = Vec::with_capacity(size);
for v in self {
result.extend_from_slice(v.borrow())
}
result
}
One possible solution might be to use the Chain
iterator:
let abc: Vec<_> = a.iter().chain(b).chain(c).collect();
However, in your example you are borrowing the slices, so we'll need to either deref each borrowed element or use the Cloned
iterator to copy each integer. Cloned
is probably a bit easier and as efficient as we are working with small Copy
data (i32
):
let abc: Vec<_> = a.iter().cloned()
.chain(b.iter().cloned())
.chain(c.iter().cloned())
.collect();
Seeing as each of these iterators are ExactSizeIterator
s, it should be possible to allocate the exact size for the target Vec
up front, however I'm unware whether or not this is actually the case in the std implementation (they might be waiting on specialization to land before adding this optimisation).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With