Search code examples
vectorrustconcatenation

How to concatenate immutable vectors in one line?


I have immutable vectors a and b where the elements are cheap to copy and I want to create a vector that forms the concatenation of these existing vectors without changing them (*).

An earlier question addressed it if one of the vectors is mutable, so an obvious answer is to first clone vector a, e.g.

let mut r = a.clone();
r.extend(&b);

but that seems neither elegant nor efficient (extending can easily cause one needless reallocation, right?). The (corrected) best alternative I (being a Rust noob) come up with is:

fn cat(a: &Vec<i32>, b: &Vec<i32>) -> Vec<i32> {
    let mut r = Vec::<i32>::with_capacity(a.len() + b.len());
    r.extend(a);
    r.extend(b);
    r
}

Since these elements are cheap to copy, the answer to the more generic question for vectors of strings should apply here, but vec![a, b].concat() only seems to work if you construct the vector of vectors by moving the vectors into it, because vec![&a, &b].concat()yields "no method named concat found".

Is there a one-liner for this seemingly simple job, even if it's not optimal?

---------- (*) turns out there are two meanings to "without changing":

  • Just immutable, which in Rust means that if code compiles, it will not see the variable with a changed value; but the variable's value may be moved out, and future code cannot use the variable anymore.
  • Actually read-only, leaving the variable untouched for further or future code; this is what I am looking for.

Solution

  • concat does work, if used correctly:

    fn cat(a: &[i32], b: &[i32]) -> Vec<i32> {
        [a, b].concat()
    }
    
    fn main() {
        let a = vec![1, 2, 3];
        let b = vec![7, 8, 9];
        println!("{:?}", cat(&a, &b));
    }