Simeon
Simeon

Reputation: 818

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:

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.

Upvotes: 9

Views: 5416

Answers (2)

Andy Prowl
Andy Prowl

Reputation: 126432

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.

Upvotes: 10

jpo38
jpo38

Reputation: 21514

Try this:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    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::set_union( a.begin(), a.end(), b.begin(), b.end(), input.begin() );

    for ( std::vector<int>::const_iterator iter = input.begin();
          iter != input.end();
          ++iter )
    {
        std::cout << *iter << " ";
    }

    return 0;
}

It outputs:

1 2 3 4 5 6 7 8 99 

Upvotes: 0

Related Questions