Search code examples
c++performancestdvector

Repeat contents of a std::vector


Suppose I have a vector (potentially large) of trivial types, e.g.

std::vector<int> v{1,2,3};

What is the best way to repeat it n times?

E.g. 3 times would give the result {1,2,3,1,2,3,1,2,3}

Surely, this is a problem that arises often (numeric libraries usually have such a function build in). My naive solution:

template<typename T>
std::vector<T> repeat(const std::vector<T> &input, unsigned int times) {
    std::vector<T> result;
    auto input_size = input.size();
    result.reserve(input_size * times);
    for (std::size_t rep = 0; rep < times; ++rep) {
        for (std::size_t i = 0; i < input_size; ++i) {
            result.push_back(input[i % input_size]);
        }
    }
    return result;
}

Surely this can be made faster? Maybe with std::copy? In that case, however, I'm not sure how to tell the vector its new size while avoiding zero-initialization. Apparently it cannot be done easily (see, e.g., 1). I tried to do it with iterators as well, but it didn't seem to be faster.


Solution

  • With range-v3 you could write:

    #include <range/v3/all.hpp>
    namespace rv = ranges::views;
    
    template<typename T>
    auto repeat(const std::vector<T> &input, unsigned int times) 
    {
        return rv::repeat_n(input, times) 
               | rv::join 
               | ranges::to<std::vector<T>>;
    }
    

    Here's a demo.

    I suspect this will have sufficiently good performance for your needs.