Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing part of std::vector by smaller std::vector

I wonder what would be the correct way to replace (overwriting) a part of a given std::vector "input" by another, smaller std::vector? I do neet to keep the rest of the original vector unchanged. Also I do not need to bother what has been in the original vector and I don't need to keep the smaller vector afterwards anymore.

Say I have this:

std::vector<int> input = { 0, 0, 1, 1, 2, 22, 3, 33, 99 };
std::vector<int> a = { 1, 2, 3 };
std::vector<int> b = { 4, 5, 6, 7, 8 };

And I want to achieve that:

input = { 1, 2, 3, 4, 5, 6, 7, 8, 99}

What is the right way to do it? I thought of something like

input.replace(input.beginn(), input.beginn()+a.size(), a);
// intermediate input would look like that: input = { 1, 2, 3, 1, 2, 22, 3, 33, 99 };

input.replace(input.beginn()+a.size(), input.beginn()+a.size()+b.size(), b);

There should be a standard way to do it, shouldn't it? My thoughts on this so far are the following:

  • I can not use std::vector::assign for it destroys all elements of input

  • std::vector::push_back would not replace but enlarge the input --> not what I want

  • std::vector::insert also creates new elements and enlages the input vector but I know for sure that the vectors a.size() + b.size() <= input.size()

  • std::vector::swap would not work since there is some content of input that needs to remain there ( in the example the last element) also it would not work to add b that way

  • std::vector::emplace also increases the input.size -> seems wrong as well

Also I would prefer if the solution would not waste performance by unnecessary clears or writing back values into the vectors a or b. My vectors will be very large for real and this is about performance in the end.

Any competent help would be appreciated very much.

like image 513
Simeon Avatar asked Jan 18 '15 19:01

Simeon


1 Answers

You seem to be after std::copy(). This is how you would use it in your example (live demo on Coliru):

#include <algorithm> // Necessary for `std::copy`...

// ...

std::vector<int> input = { 0, 0, 1, 1, 2, 22, 3, 33, 99 };
std::vector<int> a = { 1, 2, 3 };
std::vector<int> b = { 4, 5, 6, 7, 8 };    

std::copy(std::begin(a), std::end(a), std::begin(input));
std::copy(std::begin(b), std::end(b), std::begin(input) + a.size());

As Zyx2000 notes in the comments, in this case you can also use the iterator returned by the first call to std::copy() as the insertion point for the next copy:

auto last = std::copy(std::begin(a), std::end(a), std::begin(input));
std::copy(std::begin(b), std::end(b), last);

This way, random-access iterators are no longer required - that was the case when we had the expression std::begin(input) + a.size().

The first two arguments to std::copy() denote the source range of elements you want to copy. The third argument is an iterator to the first element you want to overwrite in the destination container.

When using std::copy(), make sure that the destination container is large enough to accommodate the number of elements you intend to copy.

Also, the source and the target range should not interleave.

like image 167
Andy Prowl Avatar answered Nov 06 '22 03:11

Andy Prowl