Replacing part of std :: vector with smaller std :: vector

Interestingly, what would be the right way to replace (rewrite) part of a given std :: vector "input" with another smaller std :: vector? I try to keep the rest of the original vector unchanged. Also I don’t need to worry about what was in the original vector and I don’t need to keep the smaller vector later.

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 this:

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

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

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

// intermediate input will look like this: input = {1, 2, 3, 1, 2, 22, 3, 33, 99};

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

There must be a standard way to do this, right? My thoughts on this are still the following:

  • I can not use std :: vector :: assign for it destroys all input elements
  • std :: vector :: push_back will not replace, but increase input -> not what I want

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

  • std :: vector :: swap will not work, since there is some input content that should remain there (in the example, the last element) will also not work, to add b this way
  • std :: vector :: emplace also increments input.size β†’ as well

I would also prefer that the solution does not lose performance due to unnecessary cleanups or writing values ​​to vectors a or b. My vectors will be very large for real, and this is ultimately about performance.

Any competent help would be greatly appreciated.

+5
source share
2 answers

It seems you are after std::copy() . So you can 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 the 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); 

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

The first two arguments to std::copy() indicate the original range of elements that you want to copy. The third argument is the iterator of the first element that 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 that you are going to copy.

In addition, the source and the target range should not alternate.

+6
source

Try the following:

 #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 
0
source

Source: https://habr.com/ru/post/1211372/


All Articles