开发者

stdlib "Unique" method does not work

开发者 https://www.devze.com 2023-04-06 17:22 出处:网络
I\'m trying to use the C++ Standard Library algorithm unique (with BinaryPredicate). I\'ve created a vector of pairs; each pair is like \"(first=a vector of 4 doubles, second=an integer)\". The seco

I'm trying to use the C++ Standard Library algorithm unique (with BinaryPredicate).

I've created a vector of pairs; each pair is like "(first=a vector of 4 doubles, second=an integer)". The second element serves as index so after using `unique, I can still tell the original index.

In the example below, I've created something like this:


10 20 30 40, 1
10 20 30 40, 2
10 20 30 40, 3
10 20 30 40, 4
10 20 30 40, 5
10 20 30 40, 6

Now I want to use the unique function to compare only the first element of each pair. I've used a customize binary predictor uniquepred. Indeed, it works, but the vector is not reduced after using unique.

EXPECTED RESULT

Size before=6
equal!
equal!
equal!
equal!
equal!
Size after=1

ACTUAL RESULT

Size before=6
equal!
equal!
equal!
equal!
equal!
Size after=6

Minimum working example follows. Please help me debugging this.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef std::vector<double> V1db;
typedef std::pair<V1db, int > Pairs;
typedef std::vector<Pairs> Vpairs;

bool uniquepred( const Pairs& l, const Pairs& r) {
    if (l.first==r.first)
        cout<<"equal!"<<endl;
    return l.first == r.first;
}
int main()
{
    Vpairs ak;
    V1db u2(4);
    u2[0]=10;u2[1]=20;u2[2]=30;u2[3]=40;
    Pairs m2;
    m2.first = u2;
    m2.second= 1;
    ak.push_back(m2);
    m2.second= 2;
    ak.push_back(m2);
    m2.second= 3;
    ak.push_back(m2);
    m2.second= 4;
    ak.push_back(m2);
    m2.second= 5;
    ak.push_back(m2);
    m2.second= 6;
    ak.push_back(m2);
    cout<<"Size before="<<ak.size()<<endl;
 开发者_运维问答   unique(ak.begin(), ak.end(), uniquepred);
    cout<<"Size after="<<ak.size()<<endl;

    return 0;
}


You want to do:

ak.erase(unique(ak.begin(), ak.end(), uniquepred), ak.end());

The reason for this is that std::unique reorders the values. It doesn't delete them though and you are left with a new range, from begin() to the iterator that unique returns. The container itself is not altered, other than this reordering.

There's no "remove at position X" method on vectors, even if there was it would invalidate the iterators. The unique algorithm by design doesn't even know anything about the underlying container, so it can work with any valid pair of iterators. The only requirement is that they are ForwardIterators.


std::unique does work; you forgot to look it up in your favourite C++ library documentation to find out what it does.

It functions a little weirdly, like std::remove, in that it actually just moves stuff around and gives you the end iterator to the new range. The underlying container is not resized: you have to do erasure yourself:

ak.erase(std::unique(ak.begin(), ak.end(), uniquepred), ak.end());
0

精彩评论

暂无评论...
验证码 换一张
取 消