tags:

views:

173

answers:

4

I'm using multitreading and want to merge the results.

ex:

std::vector<int> A;
std::vector<int> B;
std::vector<int> AB;

I want AB to have to contents of A and the contents of B in that order. What's the most efficient way of doing something like this?

Thanks

A: 

If your vectors are sorted*, check out set_union from <algorithm>.

set_union(A.begin(), A.end(), B.begin(), B.end(), AB.begin());

There's a more thorough example in the link

*thanks rlbond

Cogwheel - Matthew Orlando
`set_union` only works on sorted ranges.
rlbond
also, it does not do the same thing as a straight append - the elements in the output range are unique, which may not be what the OP wanted (they might not even be comparable). It's certainly not the most efficient way of doing it.
Peter
+18  A: 
AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );
Kirill V. Lyadvinsky
Thanks! Wouldn't have thought of reserve.
Milo
+3  A: 

This is precisely what std::vector::insert is for.

std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), b.end());
Shirik
Except `std::vector::insert` is godawful slow when all you're trying to do is concatenate two vectors. This is where `<algorithm>` is fail and you really wish `std::vector::extend` was a real method.
Nick Bastin
@Nick: Slow compared to what?
GMan
Maybe that it checks for enough space on each insert of element? Using reserve beforehand will speed it up.
PoweRoy
@GMan: It's slow compared to knowing how to preallocate the final size.
Nick Bastin
@Nick: I wouldn't be surprised if every modern stdlib implementation specialized `insert` on random-access iterators and reserved up-front.
GMan
@Gman: That's a fair point since we know that the source is also a vector (where iterator `distance` has O(1) complexity). Still, the performance guarantees of `insert` are something to be mindful of when you can often do better by planning ahead.
Nick Bastin
+2  A: 

Depends on whether you really need to physically concatenate the two vectors or you want to give the appearance of concatenation of the sake of iteration. The boost::join function

http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html

will give you this.

std::vector<int> v0;
v0.push_back(1);
v0.push_back(2);
v0.push_back(3);

std::vector<int> v1;
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
...

BOOST_FOREACH(const int & i, boost::join(v0, v1)){
    cout << i << endl;
}

should give you

1
2
3
4
5
6

Note boost::join does not copy the two vectors into a new container but generates a pair of iterators (range) that cover the span of both containers. There will be some performance overhead but maybe less that copying all the data to a new container first.

bradgonesurfing
+1 for boost::join
Sam Miller