Best way to concatenate vectors in Rust

91,940

Solution 1

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 2

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)
Share:
91,940
Joe Thomas
Author by

Joe Thomas

Let me know if you're into Bitcoin

Updated on September 16, 2020

Comments

  • Joe Thomas
    Joe Thomas over 3 years

    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?

  • Damian Dziaduch
    Damian Dziaduch almost 5 years
    What is the difference between consuming, cloning and coppying? I thought that there are only references (borrowing, yes?) and clones
  • Stargateur
    Stargateur almost 5 years
    @DamianDziaduch wow, that broad, you ask me to explain Rust ;) If you have experience you could understand the following: basically consume move the data so a and b are not available anymore, the result is free to do what it want. Reference just borrow both vector, so you need to keep their alive as long the result want to live. Clone and Copy are very close, the first one can be expensive, the second one should be cheap. They just use both vector as a source without need them latter, so the result become free to live as long as it want as well that a and b. Hope it's clear.
  • Stargateur
    Stargateur over 3 years
    I see chain is still broken on this... that sad. your bench_concat_iter_chain do nothing, iterator are lazy
  • User
    User almost 3 years
    How does the performance compare to equivalent versions of extend?
  • Stargateur
    Stargateur almost 3 years
    running this on rustc 1.55.0-nightly (885399992 2021-07-06) have much better result, houra !
  • User
    User almost 3 years
    @Stargateur sorry what do you mean? Your reply appears at the bottom to me. And a nice result with what?
  • Michael Dorst
    Michael Dorst over 2 years
    How is cloning cheaper than copying? How are they different?
  • Stargateur
    Stargateur over 2 years
  • Michael Dorst
    Michael Dorst over 2 years
    @Stargateur Based on that it seems to me that cloning could be either cheaper or more expensive than copying, depending on the type. Pretty sure for i32 it should be exactly the same.