vector unique problem

Pages: 12
..........
Last edited on
Thanks kbw but how do I do it for struct type of vector?
if "DateTime" is same and "ID and BS" are different, then the elements are considered equal
so, if all the data is equal, the elements are different?

IIRC the comp object is suppose to tell when two objects are equal. You are doing the opposite.

Also
1
2
3
bool LC_419::operator<(const LC_419& p) const{
  return LC_419DateTime < p.LC_419DateTime;
}
No, if the DateTime is equal in any two elements and the IDs are different and BS are different, then remove that element.

Could you please help
I've hacked the wikipedia example. The set is static because comp is passed by value, there must be an elegant solution, but it doesn't come to mind right now.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <algorithm> // remove and remove_if
#include <set>
#include <iostream>

struct record
{
        record() { i = j = 0; }
        record(int i, int j) : i(i), j(j) {}
        int i, j;
};
std::ostream& operator<<(std::ostream& os, const record& r)
{
  os << '(' << r.i << ',' << r.j << ')';
  return os;
}

class remove_dup
{
  typedef std::set<int> iset;
  static iset recs;
public:
  bool operator()(const record& r)
  {
    iset::iterator p = recs.find(r.i);
    if (p == recs.end())
    {
      recs.insert(r.i);
      return false;
    }
    return true;
  }
};
remove_dup::iset remove_dup::recs;
 
int main()
{
  using namespace std;
  record elements[] = { record(0, 0), record(0, 1), record(0, 2), record(1, 0), record(1, 3) };
  vector<record> v(elements, elements + 5); 

  remove_dup comp;
  v.erase( remove_if(v.begin(), v.end(), comp), v.end() ); 

  for (size_t i = 0; i != v.size(); ++i)
    cout << v[i] << ", ";
  cout << endl;
  return 0;
}

1
2
3
bool remove_dup::operator()(const record &r){
    return not recs.insert(r.i).second;
}


Why are you against unique? (except that the data must be sorted)
1
2
3
4
5
struct unique{
    bool operator()(const record &a, const record &b){
        return a.i == b.i;
    }
};
I believe it's enough to define operators < and == properly and then just call (stable) sort, unique and erase.

@OP:
Also, when you have duplicates, which ones do you want to keep? The ones with high ID? Low ID? High BS? Low BS? My guess is that, since you use stable sort, you want to keep them the way they were pushed back in the container. But if the ID and BS info is important, it should be taken into account in your < operator. I'll borrow kbw's code for this...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct record
{
    record() { i = j = 0; }
    record(int i, int j) : i(i), j(j) {}
    int i, j;

    bool operator<(const record & r) const
    {
        if (i<r.i) return true;
        if (i>r.i) return false;

        //now, i==r.i

        //if we want to keep records with
        //high j, we have to put them first

        if (j>r.j) return true;

        return false;
    }

    bool operator==(const record & r) const {return i==r.i;}
};

ostream& operator<<(ostream& os, const record& r)
{
    os << '(' << r.i << ',' << r.j << ')'; return os;
}

int main()
{
    record elements[] = { record(0, 0), record(0, 1),
        record(0, 2), record(1, 0), record(1, 3) };

    vector<record> v(elements, elements + 5);

    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());

    for (size_t i = 0; i != v.size(); ++i)
        cout << v[i] << " ";

    cout << endl; cin.get();
    return 0;
}

Last edited on
The set is static because comp is passed by value
I can't understand how that can be a problem. There should be just 1 object in all the loop.
However:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct D{
	bool operator()(int){
		return true; //doesn't matter
	}
	~D(){
		std::cerr <<'D';
	}
};

int main() {
	vector<int> v;
	remove_if(v.begin(), v.end(), D());
	return 0;
}
DDD
?
Bumping, for undefined behaviour.
The idea behind functor objects is to maintain an estate.
However that function "arbitrarily" kills the object. I suppose it calls itself (what for?).

still: how can 2 more objects be created in a function that have to do nothing
Thank you very much all of you but how do I solve my problem? Could anyone please help me do it according to my problem.

Regards
remove the not in only_unique::operator()
If the problem persists, provide a test case, please.
..........
Last edited on
Input (fat removed)
0
2010-10-07 08:26:00.067
1585955916
S

1
2010-10-07 08:26:00.067
1585955916
S

2
2010-10-07 08:26:00.067
1585955917
B

3
2010-10-07 08:26:00.067
1585955917
B

4
2010-10-07 08:26:00.067
1585955916
S

5
2010-10-07 08:26:00.067
1585955917
B

6
2010-10-07 08:26:00.067
1585955917
B

7
2010-10-07 08:26:00.067
1585955916
S
Output (the ones that survive)
0 1 4 7


What is the expected output?

Hello ne555

The expected output should be

1
2
3
4
5
6
7
8
9
3
2010-10-07 08:26:00.067
1585955917
B

4
2010-10-07 08:26:00.067
1585955916
S


Thanks


So you just want 1 record with the corresponding Date, ID and B/S, but that should be the last input.

Maybe
1
2
3
4
5
6
7
8
9
10
11
struct only_unique{
  bool operator( const LC_419 & a , const LC_419& b ) const{
    return a.Date==b.Date and a.ID == b.ID and a.BS == b.BS;  //al equal, then remove it
  }
};

std::stable_sort( v.begin(), v.end(), BS() );
std::stable_sort( v.begin(), v.end(), ID() );
std::stable_sort( v.begin(), v.end(), Date() ); //sorted by the 3 keys

std::unique( v.rbegin(), v.rend(), only_unique() ); //the last one survives 
Last edited on
Alright THANKS ne555 :-)
And why did you delete your posts? You really should leave it for the benefit of the community.
+1 kbw

Erasing your posts after you get an answer is a jerk move. Don't do it.
Pages: 12