Reputation: 1119
In the following C++ code, I am trying to use sort function to sort one vector based on another one. For example, if v1 = (1, 2, 3, 4, 5)
and v2 = (-1.1, 1.5, 0.2, 4, 3)
, then after calling my function relative_sort (v1,v2)
we should have v1 = (1, 3, 2, 5, 4)
. I don't understand why the code does not work properly.
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
void print_vector (vector<double> & v)
{
for (int i = 0 ; i < v.size() ; i++)
cout << v[i] << ' ' ;
}
void relative_sort (vector<double> & v1 , vector<double> & v2) // sort v1 based on v2
{
int n = v1.size();
if ( n != v2.size())
cout << endl << "Error: The length of v1 is not the same as v2" << endl ;
else if (n<1)
cout << endl<< "Error: Empty Vectors" << endl ;
else
{
std::sort(v1.begin(), v1.end(), [&v2](int a, int b) { return v2[a] < v2[b]; } );
}
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
vector <double> v2 ;
vector <double> v1 ;
vector <double> v0 ;
double a[] = {0,1,2,3,4};
v0.assign(a,a+5);
double b[] = {1,2,3,4,5};
v1.assign(b,b+5);
double c[] = {-1.1 , 1.5 , 0.2 , 4, 3};
v2.assign(c,c+5);
cout << endl << "V0: " ;
print_vector(v0) ;
cout << endl << "V1: " ;
print_vector(v1) ;
cout << endl << "V2: " ;
print_vector(v2) ;
cout << endl ;
relative_sort (v0 , v2);
cout << endl << "V0: " ;
print_vector(v0) ;
relative_sort (v1 , v2);
cout << endl << "V1: " ;
print_vector(v1) ;
return 0;
}
The output of the above code is
V0: 0 1 2 3 4
V1: 1 2 3 4 5
V2: -1.1 1.5 0.2 4 3
V0: 0 2 1 4 3
V1: 5 2 1 4 3
The output for v0
is correct while it is not for v1
. It seems that it works only for v0
and not for any other vector!
Upvotes: 0
Views: 73
Reputation: 206567
Your code has undefined behavior since not all values from v1
are valid indices for v2
. In particular, 5
is an invalid index for v2
.
Here's a way accomplish what you want to:
std::vector<std::pair<double, double>>
created from v1
and v2
.v1
.Here's an updated version of the function.
void relative_sort (vector<double> & v1 , vector<double> & v2) // sort v1 based on v2
{
size_t n = v1.size();
if ( n != v2.size())
cout << endl << "Error: The length of v1 is not the same as v2" << endl ;
else if (n<1)
cout << endl<< "Error: Empty Vectors" << endl ;
else
{
std::vector<std::pair<double, double>> v3(n);
for ( size_t i = 0; i < n; ++i )
{
v3[i] = {v1[i], v2[i]}
}
std::sort(v3.begin(), v3.end(), [](std::pair<double, double> a,
std::pair<double, double> b)
{ return a.second < b.second; } );
for ( size_t i = 0; i < n; ++i )
{
v1[i] = v3[i].first;
}
}
}
You can probably use boost::zip_iterator
to simplify that task but I have not used it myself.
Update, in response to OP's comment.
If you change v1
to be of type std::vector<size_t>
instead of std::vector<double>
and make sure that it contains {0, 1, 2, 3, 4}
, then you may use:
std::sort(v1.begin(), v1.end(),
[&v2](size_t a, size_t b) { return v2[a] < v2[b]; } );
to sort the indices without a problem.
You can also update your function so that v1
is resized to match the size of v2
and make sure to set the indices correctly before calling sort
.
// Get sorted indices in v1 based on values in v2
void relative_sort (vector<size_t> & v1 , vector<double> & v2)
{
size_t n = v2.size();
if (n<1)
cout << endl<< "Error: Empty Vectors" << endl ;
else
{
v1.resize(n);
for ( size_t i = 0; i < n; ++i )
{
v1[i] = i;
}
std::sort(v1.begin(), v2.end(),
[&v2](size_t a, size_t b) { return v2[a] < v2[b]; } );
}
}
Upvotes: 2