1

I have a structure as shown below.

struct Num {
    uint64_t key;
    uint64_t val;
};

// Compare based on their key and value.
bool num_less(Num a, Num b)
{
    if(a.key < b.key)
        return true;
    else if(a.key == b.key)
    {
        if(a.val < b.val)
            return true;
        else
            return false;
    }
    else
        return false;
}

// Compare based on their key and value.
bool num_equal(Num a, Num b)
{
    return ((a.key == b.key) && (a.val == b.val)) ? true : false;
}

I have a vector of structs. I want to remove the duplicates from that vector. I tried the following approach.

  1. Sort the vector
  2. Remove the duplicates(consecutively placed)

    vector<Num> arr;

    sort(arr.begin(), arr.end(), num_less);

    arr.erase(std::unique(arr.begin(), arr.end(), num_less);, arr.end());

But when I run the above code, only the first element of the sorted vector is printed and rest of them are somehow deleted. I am not sure what am I doing wrong.

Edit - I tried with num_equal function in std::unique. And it worked.

7
  • 1
    You need to provide an overloaded equality operator operator== for your struct. Commented Nov 11, 2015 at 13:49
  • Actually I added the num_equal function in std::unique. But it didn't work. Commented Nov 11, 2015 at 13:51
  • 2
    From en.cppreference.com/w/cpp/algorithm/unique, the 3rd argument is a "binary predicate which returns ​true if the elements should be treated as equal." So you should use num_equal instead of num_less. Commented Nov 11, 2015 at 13:57
  • 1
    Rule of thumb: only use the constants true and false to initialise variables, and never elsewhere. Your test are terribly convoluted, you can just write return a.val < b.val; instead of if (a.val < b.val) return true; else return false;, for instance. The whole first function should be written as return (a.key < b.key) or (a.key == b.key and a.val < b.val); Equivalently, the second would be return (a.key == b.key) and (a.val == b.val); Commented Nov 11, 2015 at 14:07
  • Try to use a std::set instead of std::vector. Commented Nov 11, 2015 at 14:31

1 Answer 1

2

you need to define equal predicate

struct Num 
{
    unsigned int key;
    unsigned int val;
};

bool num_less(const Num &a, const Num &b)
{
    return (a.key<b.key)||(!(b.key < a.key))&&(a.val<b.val));
}
bool num_equal(const Num &a, const Num &b)
{
    return (a.key==b.key)&&(a.val==b.val);
}
int main()
{
    vector<Num> arr;
    Num temp;
    // add some examples
    temp.key=10; temp.val=20;
    arr.push_back(temp);        arr.push_back(temp);
    temp.key=11; temp.val=23;
    arr.push_back(temp);        arr.push_back(temp);
    temp.key=10; temp.val=20;
    arr.push_back(temp);        arr.push_back(temp);    arr.push_back(temp);
    //sort
    sort(arr.begin(),arr.end(),num_less);
    //delete dublicates
    arr.erase(unique(arr.begin(),arr.end(),num_equal),arr.end());
    return 0;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Your num_less is wrong and can be rewritten correctly as return std::tie(a.key, a.val) < std::tie(b.key, b.val);
you are right it is num_great, but the code works correctly, because of it deletes all dublicats.
Yeah, my num_less was messed up. I changed it and it's working fine now.
@h.o.m.a.n: currently, your num_less is equivalent to (a.key < b.key) ||(a.val < b.val), so {1, 2} < {2, 1} but also {2, 1} < {1, 2}...
So you have a typo in !(a.key < b.key) which should be !(b.key < a.key).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.