0x1a4
0x1a4

Reputation: 111

Create new Vec<T> from a vector Vec<T> and data T

I want to be able to create a new vector c: Vec<T> from a: Vec<T> and b: T where c is equal to b appended to a, without using mutables. Say I have this code-

fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
    return Vec::<T>::new(a, b);
}

I am aware this does not work, because Vec::new() has no input parameters. What I am wondering is if there is an function or macro in std::vec that can initialize a vector from another vector and a set of additional values to append onto the vector. I know a function can be created very easily to do this, I am just wondering if functionality exists in the standard library to work with vectors without them being mutable in the first place.

Upvotes: 2

Views: 1289

Answers (3)

user4815162342
user4815162342

Reputation: 155046

Note that you can use the tap crate to push b to a in an expression that evaluates to a:

use tap::Tap;

fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
    a.tap_mut(|a| a.push(b))
}

This combines the performance benefits of push() (in comparison to building a brand new vector) with the elegance of having a short expression.

Upvotes: 2

Micron Mushroom
Micron Mushroom

Reputation: 97

Vec::from_iter should work if you're willing to use iterators.

pub fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
    return Vec::from_iter(a.into_iter().chain(std::iter::once(b)));
}

Edit(s): Also as far as I have seen: the most common way to work with vectors, slices, and arrays is through the use of the Iterator trait and the functionality it provides.

Also on the topic of speed: the above approach is slightly faster if you avoid cloning. On my computer iterators take about 1.571µs per call whereas cloning and pushing to a vector took 1.580µs per call. (Tested by running the functions 300 000 times on a debug build.)

Upvotes: 0

Kaplan
Kaplan

Reputation: 3728

The universal form of the inefficient solution should look like this:

fn concat_vec<T>(a: Vec<T>, b: T) -> Vec<T> {
    Vec::from_iter(a.into_iter().chain(std::iter::once(b)))
}

…but its strongly recommended to use push:

fn concat_vec<T: std::clone::Clone>(a: Vec<T>, b: T) -> Vec<T> {
    let mut rslt = a.to_vec();
    rslt.push(b);
    rslt
}

Upvotes: 0

Related Questions