Jaydeep Solanki
Jaydeep Solanki

Reputation: 2945

std::set containing pair with custom comparator

I have a vector < pair <double, int> >, where double represents weight of a person and int represents the id of that person.

Now I need to convert it to set < pair < double, int > > to remove the duplicates based on the id of that person, but inside the vector I have data with some loose precision.

Example data:

-----------------------
    double |   int
-----------------------
    10.234 |  1     <--
    20.123 |  2
    10.2   |  1     <--
    30.33  |  3

As we can see, id 1 has weights in different precision.

Using the default comparator of std::set will result in having 4 elements in the set, but I need only 3.

Only 1 element with id 1 should be there in the set (anyone from the two competitors will do).

The reason I'm not using std::map is, because I need the entries to be in a specific sequence: I need them to be ordered by weight. For this reason, I'm using the following comparator:

struct comp__f {
    bool operator() (const pair<double, int>& lhs, const pair<double, int>& rhs) const{
        if(lhs.first < rhs.first) return true;
        if(lhs.first > rhs.first) return false;
        return lhs.second > rhs.second;
    }
};

Note: The question is still open, @Robᵩ's answer doesn't solve the problem entirely, but I appreciate his effort.

Upvotes: 0

Views: 6302

Answers (3)

honk
honk

Reputation: 9743

I know, I'm late to the party, but I had a similar problem and I think I solved it. Robᵩ was already on the right track, but your original lines need to be modified, too. All in all, I came up with the following comparator:

struct comp__f {
    bool operator() (const pair<double, int>& lhs, const pair<double, int>& rhs) const {
        return (lhs.second != rhs.second) && (lhs.first < rhs.first),
    }
};

As Robᵩ explained, the (lhs.second != rhs.second) part makes sure, that the IDs are unique. If this is guaranteed, then you just need to compare the weights using <. So, (lhs.first < rhs.first) ensures that the unique entries in the set get ordered by their weights.

Code on Ideone

Upvotes: 0

Coder777
Coder777

Reputation: 1035

Try this out

#include<set>
#include<iostream>
using namespace std;

class CustomComparitor
{
    public:
        int operator()(const pair<double,int>& lhs, const pair<double,int>& rhs)
        {
            return lhs.second < rhs.second;
        }
};
int main()
{
    set<pair<double,int>,CustomComparitor> myset;
    myset.insert(make_pair(1.4, 2));
    myset.insert(make_pair(1.5, 2));
    myset.insert(make_pair(1.6, 1));
    myset.insert(make_pair(1.4, 3));

    for(auto itr = myset.begin(); itr!=myset.end();itr++)
    {
        cout<<itr->first<<"  "<<itr->second<<endl;
    }
    return 0;
}

Upvotes: 0

Robᵩ
Robᵩ

Reputation: 168616

Since a record cannot be less than itself, or its equivalent self, ensure that your comp function returns false if two records have the same ID, regardless of weight.

// Assuming that your previous comp_f was correct, here is the new one:
struct comp__f {
    bool operator() (const pair<double, int>& lhs, const pair<double, int>& rhs) const{
        if(lhs.second == rhs.second) return false;  // ADD THIS LINE
        if(lhs.first < rhs.first) return true;
        if(lhs.first > rhs.first) return false;
        return lhs.second > rhs.second;
    }
};

Upvotes: 4

Related Questions