Best way to concatenate vectors in Rust

VectorRustConcatenation

Vector Problem Overview


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?

Vector Solutions


Solution 1 - Vector

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]);

Solution 2 - Vector

> 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.

Solution 3 - Vector

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoe ThomasView Question on Stackoverflow
Solution 1 - Vectoruser4268862View Answer on Stackoverflow
Solution 2 - VectorStargateurView Answer on Stackoverflow
Solution 3 - VectorTianyi ShiView Answer on Stackoverflow