What is the best way to concatenate vectors in Rust? - vector

Is it even possible to concatenate vectors in Rust? If so, is there an elegant way to do so? I have something like this:
let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];
for val in &b {
a.push(val);
}
Does anyone know of a better way?

The structure std::vec::Vec has method append():
fn append(&mut self, other: &mut Vec<T>)
Moves all the elements of other into Self, leaving other empty.
From your example, the following code will concatenate two vectors by mutating a and b:
fn main() {
let mut a = vec![1, 2, 3];
let mut b = vec![4, 5, 6];
a.append(&mut b);
assert_eq!(a, [1, 2, 3, 4, 5, 6]);
assert_eq!(b, []);
}
Alternatively, you can use Extend::extend() to append all elements of something that can be turned into an iterator (like Vec) to a given vector:
let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];
a.extend(b);
assert_eq!(a, [1, 2, 3, 4, 5, 6]);
// b is moved and can't be used anymore
Note that the vector b is moved instead of emptied. If your vectors contain elements that implement Copy, you can pass an immutable reference to one vector to extend() instead in order to avoid the move. In that case the vector b is not changed:
let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];
a.extend(&b);
assert_eq!(a, [1, 2, 3, 4, 5, 6]);
assert_eq!(b, [4, 5, 6]);

I can't make it in one line. Damian Dziaduch
It is possible to do it in one line by using chain():
let c: Vec<i32> = a.into_iter().chain(b.into_iter()).collect(); // Consumed
let c: Vec<&i32> = a.iter().chain(b.iter()).collect(); // Referenced
let c: Vec<i32> = a.iter().cloned().chain(b.iter().cloned()).collect(); // Cloned
let c: Vec<i32> = a.iter().copied().chain(b.iter().copied()).collect(); // Copied
There are infinite ways.

Regarding the performance, slice::concat, append and extend are about the same. If you don't need the results immediately, making it a chained iterator is the fastest; if you need to collect(), it is the slowest:
#![feature(test)]
extern crate test;
use test::Bencher;
#[bench]
fn bench_concat___init__(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
});
}
#[bench]
fn bench_concat_append(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
x.append(&mut y)
});
}
#[bench]
fn bench_concat_extend(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
x.extend(y)
});
}
#[bench]
fn bench_concat_concat(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
[x, y].concat()
});
}
#[bench]
fn bench_concat_iter_chain(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
x.into_iter().chain(y.into_iter())
});
}
#[bench]
fn bench_concat_iter_chain_collect(b: &mut Bencher) {
b.iter(|| {
let mut x = vec![1i32; 100000];
let mut y = vec![2i32; 100000];
x.into_iter().chain(y.into_iter()).collect::<Vec<i32>>()
});
}
running 6 tests
test bench_concat___init__ ... bench: 27,261 ns/iter (+/- 3,129)
test bench_concat_append ... bench: 52,820 ns/iter (+/- 9,243)
test bench_concat_concat ... bench: 53,566 ns/iter (+/- 5,748)
test bench_concat_extend ... bench: 53,920 ns/iter (+/- 7,329)
test bench_concat_iter_chain ... bench: 26,901 ns/iter (+/- 1,306)
test bench_concat_iter_chain_collect ... bench: 190,334 ns/iter (+/- 16,107)

I think the best method to concatenate one or more vector is this:
let first_number: Vec<usize> = Vec::from([0]);
let final_number: Vec<usize> = Vec::from([3]);
let middle_numbers: Vec<usize> = Vec::from([1,2]);
let numbers = [input_layer, middle_layers, output_layer].concat();

One option is to use the extend method, which allows you to append the elements of one vector to another. Like so:
let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];
a.extend(b);
This will append the elements of b to the end of a, resulting in a vector a with the elements [1, 2, 3, 4, 5, 6].
Another way is you can use the concat function from the std::iter module to concatenate two vectors. This function takes two vectors as arguments and returns a new vector that is the concatenation of the two input vectors. Like so:
use std::iter;
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let c = iter::concat(a, b);
This will create a new vector c with the elements [1, 2, 3, 4, 5, 6].
You can also use the [..] operator to concatenate two vectors. This operator allows you to create a new vector that is the concatenation of two input vectors. Like so:
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let c = [&a[..], &b[..]].concat();
This will create a new vector c with the elements [1, 2, 3, 4, 5, 6].

made some fix on Mattia Samiolo's answer:
let first_number: Vec<usize> = Vec::from([0]);
let final_number: Vec<usize> = Vec::from([3]);
let middle_numbers: Vec<usize> = Vec::from([1, 2]);
let numbers = [first_number, middle_numbers, final_number].concat();
println!("{:?}", numbers);

Related

How to replace portion of a vector using Rust?

What is the best way to replace a specific portion of a vector with a new vector?
As of now, I am using hardcoded code to replace the vector. What is the most effective way to achieve this?
fn main() {
let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let u = vec![0,0,0,0];
v[2] = u[0];
v[3] = u[1];
v[4] = u[2];
v[5] = u[3];
println!("v = {:?}", v);
}
Permalink to the playground
Is there any function to replace the vector with given indices?
For Copy types:
v[2..][..u.len()].copy_from_slice(&u);
Playground.
For non-Copy types:
v.splice(2..2 + u.len(), u);
Playground.
Another way:
let offset : usize = 2;
u.iter().enumerate().for_each(|(index, &val)| {
v[index + offset] = val;
});
Playground

How to iterate over a two dimensional vector in rust?

I have a mutable reference of vector of mutable references of vectors I want to iterate over the vector and then change the value of its elements.
let mut a = vec![1, 2, 3];
let mut b = vec![4, 5, 6];
let mut c = vec![&mut a , &mut b];
let mut v = &mut c;
I want to iterate over v and do operations on its elements
preferably using an iterator and not by indexing.(I specifically want to iterate over a reference of a vector of references of vector and not just a 2d vector)
fn main() {
let mut a = vec![1, 2, 3];
let mut b = vec![4, 5, 6];
let mut c = vec![&mut a, &mut b];
let v = &mut c;
for row in v.iter_mut() {
for el in row.iter_mut() {
*el *= 2;
}
}
println!("{:?}", v);
}
[[2, 4, 6], [8, 10, 12]]
Or if you need the indices for the computation:
fn main() {
let mut a = vec![1, 2, 3];
let mut b = vec![4, 5, 6];
let mut c = vec![&mut a, &mut b];
let v = &mut c;
for (y, row) in v.iter_mut().enumerate() {
for (x, el) in row.iter_mut().enumerate() {
*el *= 2 * x + y;
}
}
println!("{:?}", v);
}
[[0, 4, 12], [4, 15, 30]]

Get the number of elements stored inside an n-dimensional vector

I have a 2-dimensional vector:
let vec2d = vec![
vec![1, 1, 1],
vec![1, 1, 1],
];
I can yield the total of elements stored this way:
let mut n_vec_element: i32 = 0;
for i in vec2d.iter() {
n_vec_element += i.len() as i32;
}
println!("2D vector elements :{}", n_vec_element); // prints 6
When I increase the dimensions, the loop gets longer:
let mut n_vec_element: i32 = 0;
let vec3d = vec![
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
],
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
]
];
for i in vec3d.iter() {
// I must add another iter everytime I increment the dimension by 1.
// Else, it returns the number of stored vector instead of the vector
// elements.
for j in i.iter() {
n_vec_size += j.len() as i32;
}
};
println!("3D vector elements :{}", n_vec_element); // prints 18
There must be a more concise way to do this, but I haven't figured it out yet. Initially, I tried using vector's len() function but as I said above, it returns number of vectors stored instead of its elements.
You do not need an explicit loop to do so:
let vec2d = vec![
vec![1, 1, 1],
vec![1, 1, 1],
];
let n_vec_element: usize = vec2d.iter().map(Vec::len).sum();
assert_eq!(n_vec_element, 6);
For a 3d vector, you can do the same:
let vec3d = vec![
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
],
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
]
];
let n_vec_element: usize = vec3d.iter().flatten().map(Vec::len).sum();
assert_eq!(n_vec_element, 18);
With a 4D vector, you can put 2 flatten, etc.
With the specialization feature (i.e., with the nightly compiler), you can generalize this with an unique method:
#![feature(specialization)]
trait Count {
fn count(self) -> usize;
}
impl<T> Count for T {
default fn count(self) -> usize {
1
}
}
impl<T> Count for T
where
T: IntoIterator,
T::Item: Count,
{
fn count(self) -> usize {
self.into_iter().map(|x| x.count()).sum()
}
}
fn main() {
let v = vec![1, 2, 3];
assert_eq!(v.count(), 3);
let v = vec![vec![1, 2, 3], vec![4, 5, 6]];
assert_eq!(v.count(), 6);
}

How to increment every number in a vector without the error "cannot borrow as mutable more than once at a time"?

This code is supposed to increment each value in a vector by 1:
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
let i = v.iter_mut();
for j in i {
*j += 1;
println!("{}", j);
}
println!("{:?}", &mut v);
}
It doesn't work because of the borrowing rules of Rust:
error[E0499]: cannot borrow `v` as mutable more than once at a time
--> src/main.rs:8:27
|
3 | let i = v.iter_mut();
| - first mutable borrow occurs here
...
8 | println!("{:?}", &mut v);
| ^ second mutable borrow occurs here
9 | }
| - first borrow ends here
How can I accomplish this task?
Don't store the mutable iterator; use it directly in the loop instead:
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
for j in v.iter_mut() { // or for j in &mut v
*j += 1;
println!("{}", j);
}
println!("{:?}", &v); // note that I dropped mut here; it's not needed
}
Your code will work as-is in a future version of Rust thanks to non-lexical lifetimes:
#![feature(nll)]
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
let i = v.iter_mut();
for j in i {
*j += 1;
println!("{}", j);
}
println!("{:?}", &mut v);
}
playground
You call also just use map and collect like,
>> let mut v = vec![5,1,4,2,3];
>> v.iter_mut().map(|x| *x += 1).collect::<Vec<_>>();
>> v
[6, 2, 5, 3, 4]
In my opinion the simplest and most readable solution:
#![feature(nll)]
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
for i in 0..v.len() {
v[i] += 1;
println!("{}", j);
}
println!("{:?}", v);
}

How do I get a slice of a Vec<T> in Rust?

I can not find within the documentation of Vec<T> how to retrieve a slice from a specified range.
Is there something like this in the standard library:
let a = vec![1, 2, 3, 4];
let suba = a.subvector(0, 2); // Contains [1, 2];
The documentation for Vec covers this in the section titled "slicing".
You can create a slice of a Vec or array by indexing it with a Range (or RangeInclusive, RangeFrom, RangeTo, RangeToInclusive, or RangeFull), for example:
fn main() {
let a = vec![1, 2, 3, 4, 5];
// With a start and an end
println!("{:?}", &a[1..4]);
// With a start and an end, inclusive
println!("{:?}", &a[1..=3]);
// With just a start
println!("{:?}", &a[2..]);
// With just an end
println!("{:?}", &a[..3]);
// With just an end, inclusive
println!("{:?}", &a[..=2]);
// All elements
println!("{:?}", &a[..]);
}
If you wish to convert the entire Vec to a slice, you can use deref coercion:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b: &[i32] = &a;
println!("{:?}", b);
}
This coercion is automatically applied when calling a function:
fn print_it(b: &[i32]) {
println!("{:?}", b);
}
fn main() {
let a = vec![1, 2, 3, 4, 5];
print_it(&a);
}
You can also call Vec::as_slice, but it's a bit less common:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = a.as_slice();
println!("{:?}", b);
}
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?

Resources