Delete duplicate elements from vector

May 10, 2016 at 9:08am
In my software I get the coordinates (xyz) of points. I store this informations in a vector. So my function starts with this

1
2
3
4
5
6
7
8
  vector<vector<double> > matrix;

  rows = 2*lss.size();
  matrix.resize(rows);

  for(size_t i=0; i<rows; i++) {
      matrix[i].resize(columns);
  }

Then I fill the information into the vector and sort the vector.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int j=0;
for(size_t i = 0;i<lss.size();i++) {
    int k = j+1;

    matrix[j][0]=lss[i].v[0].x;
    matrix[j][1]=lss[i].v[0].y;
    matrix[j][2]=lss[i].v[0].z;
    matrix[k][0]=lss[i].v[1].x;
    matrix[k][1]=lss[i].v[1].y;
    matrix[k][2]=lss[i].v[1].z;

    j=j+2;
}
std::sort(matrix.begin(), matrix.end(), compare2);

After this I have to write the information of the vector to a file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int o=0;

for (size_t i=0; i<(lss.size()+1); i++) {
    int k=o+1;
			
    x2=xdiff+matrix[o][0];
    y2=ydiff+matrix[o][1];
    z2=zdiff+matrix[o][2];
    a2=xdiff+matrix[k][0];
    b2=ydiff+matrix[k][1];
    c2=zdiff+matrix[k][2];
			
    fprintf(f, "X8=%f, Y8=%f, Z8=%f \n", x2,y2,z2);
    fprintf(f, "X9=%f, Y9=%f, Z9=%f \n", a2,b2,c2);
			
    o=o+2;
}


My Problem now is that some points appear multiple times. So for further processing, it would be easier to delete the duplicates from the vector and to reduce the size of the vector.But since I'm new to the use of C ++, I can't find an appropriate method to achieve this. Does someone have a hint for me, how I could delete the duplicates in the vector, after it is sorted?
Last edited on May 10, 2016 at 9:15am
May 10, 2016 at 9:35am
May 10, 2016 at 9:55am
@Thomas1965 I tried the unique algorithmen but, everytime I start the program i get an erroro message.
Debug Assertion Failed! Expression: vector subscript out of range
.

My Code looks like 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
int j=0;
for(size_t i = 0;i<lss.size();i++) {
    int k = j+1;

    matrix[j][0]=lss[i].v[0].x;
    matrix[j][1]=lss[i].v[0].y;
    matrix[j][2]=lss[i].v[0].z;
    matrix[k][0]=lss[i].v[1].x;
    matrix[k][1]=lss[i].v[1].y;
    matrix[k][2]=lss[i].v[1].z;

    j=j+2;
}
std::sort(matrix.begin(), matrix.end(), compare2);
matrix.erase(std::unique(matrix.begin(), matrix.end()),matrix.end());
matrix.push_back(std::vector<double>(3, 0));//add a new element at the end to close contour

int p = matrix.size()-1;//get adress of last element
//copy first element to end to close contour
matrix[p][0]=matrix[0][0];
matrix[p][1]=matrix[0][1];
matrix[p][2]=matrix[0][2];

int o=0;
//print vector matrix
for (size_t i=0; i<((matrix.size())); i++) {
    int k=o+1;
			
    x2=xdiff+matrix[o][0];
    y2=ydiff+matrix[o][1];
    z2=zdiff+matrix[o][2];
    a2=xdiff+matrix[k][0];
    b2=ydiff+matrix[k][1];
    c2=zdiff+matrix[k][2];
			
    fprintf(f, "X8=%f, Y8=%f, Z8=%f \n", x2,y2,z2);
    fprintf(f, "X9=%f, Y9=%f, Z9=%f \n", a2,b2,c2);
			
    o=o+2;
}
Last edited on May 10, 2016 at 9:56am
May 10, 2016 at 10:06am
What is your comparison predicate doing? Assuming it's taking two references to lists of vectors and doing some arbitrary axis-based sorting.

I think modelling coordinates this way is a bit painful - is there any reason you're not strongly modelling a Point/Coordinate? It looks like you're extracting the information from such an object then storing them in a matrix with implicit modelling.

Even if you want to store vector matrices, it's easy enough to write a Point/Coordinate class and a Matrix class composed of a number of them.

For the general case of removing duplicates from sorted vectors (with naive sorting and comparison), std::sort + std::unique should work just fine: https://ideone.com/v47Whq

However, when you talk about a vector with unique values often you might find what you actually want is a set: https://ideone.com/NQIVqY
May 10, 2016 at 10:10am
You need to use the same comparison function as you did when you sorted.
 
matrix.erase(std::unique(matrix.begin(), matrix.end(), compare2),matrix.end());
May 10, 2016 at 10:15am
@MrHutch: Sorry, but it's hard for me to understand what you are asking me for.
If you are asking what the compare2() function is doing, here's my code.
1
2
3
4
bool compare2(vector<double> const& s1, vector<double> const& s2)
{
	return atan2(s1[1],s1[0])<atan2(s2[1],s2[0]);
}

From this point i know the vector is sorted in the way I need it for further processing. I also had a look at the link for sorted vectors you send me, and from my experience I can't tell the difference between the code example and my code.
May 10, 2016 at 10:26am
@Peter87 Okay I changed my code, now the erase() function seems to work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::sort(matrix.begin(), matrix.end(), compare2);

matrix.erase(std::unique(matrix.begin(), matrix.end(),compare2),matrix.end());

matrix.push_back(std::vector<double>(3, 0));

int p = matrix.size()-1;
		
matrix[p][0]=matrix[0][0];
matrix[p][1]=matrix[0][1];
matrix[p][2]=matrix[0][2];

for (size_t i=0; i<matrix.size(); i++) {
	x2=xdiff+matrix[i][0];
	y2=ydiff+matrix[i][1];
	z2=zdiff+matrix[i][2];
			
	fprintf(f, "X8=%f, Y8=%f, Z8=%f \n", x2,y2,z2);
}

The problem now is the compare2() function. It's deleting more elements than just the duplicates. My first guess would be to try a function like this
1
2
3
4
5
6
7
8
9
bool compare(vector<double> const& s1, vector<double> const& s2)
{
    if ( s1[0] != s2[0] )
    {
       return s1[0] > s2[0];
    }

	return s1[1] > s2[1];
}

What do you think about this function, could it work for my problem?
Last edited on May 10, 2016 at 10:28am
May 10, 2016 at 10:47am
Thanks to all of you. I figured it out, how to solve the proble with the compare function.
Topic archived. No new replies allowed.