Reputation: 115
I have a struct vector looks like this:
struct table{
int k;
int r;
int c;
}
std::vector<table> myvector;
I want to sort the vector's object based on the following criteria:
r
value should be placed together (I called the accumulation of the same r
as a "group"). c
value. c
value. For instance, if myvector
is like this (each column represents a object):
k: 1 2 3 5 4 6
r: 3 3 3 2 3 2
c: 3 4 2 3 1 4
After sorting the vector should be like this:
k: 4 3 1 2 5 6
r: 3 3 3 3 2 2
c: 1 2 3 4 3 4
My solution is that first sort the vector base on r
value so that we put the same r
value together:
std::sort(myvector.begin(), myvector.end(), compare_r);
bool compare_r(table left, table right){return left.r < right.r;}
The we sort inside each group:
bool compare_c(table left, table right){return left.c < right.c;}
std::vector<table>::iterator it1, it2;
it1 = myvector.begin();
it2 = it1;
int r_now = it1 -> r;
for(; it2 != myvector.end(); ++it2){
if(it2 -> r != r_now){
std::sort(it1, it2, compare_c);
r_now = it2 -> r;
it1 = it2;
}
}
std::sort(it1, it2, compare_c);
Right now myvector
becomes:
k: 5 6 4 3 1 2
r: 2 2 3 3 3 3
c: 3 4 1 2 3 4
The final step is to put objects with k = 5 & 6 to the back of the vector because 1st group's 1st c = 3 is larger than the 1st c = 1 of the 2nd group (third criteria). I can copy k = 5 & 6 and erase them, then insert them at the end of myvector
. But that seems like not very efficient. Does anyone has a better idea?
Upvotes: 0
Views: 170
Reputation: 44238
Here is possible implementation of idea suggested by @IgorTandetnik:
std::vector<table> myvector;
// sort based by c
std::sort( myvector.begin(), myvector.end(), []( const auto &l, const auto &r ) {
return l.c < r.c;
} );
std::unordered_map<int,int> ranks;
// populate ranks based on smallest (first) c
std::transform( myvector.begin(), myvector.end(), std::inserter( ranks ), []( const auto &t ) { return std::make_pair( t.r, t.c ); } );
// stable sort by ranks of r
std::stable_sort( myvector.begin(), myvector.end(), [&ranks]( const auto &l, const auto &r ) {
return ranks[l.r] < ranks[r.r];
} );
I did not try to compile the code, as you did not provide MCVE, but it should work after fixing syntax errors if any.
Upvotes: 1