unique operation

Dear all,

I am trying to figure out some operations of algorithm in C++. One of them is unique and its return value. Quoting from cplusplus.com:
An iterator to the element that follows the last element not removed.
The range between first and this iterator includes all the elements in the sequence that were not considered duplicates.

To check it, I wrote a script in C++ as following:
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
#include <iostream>
#include <iomanip>
#include <algorithm> //unique
#include <vector>
using namespace std;
/*
Function declaration
*/
template <class T>
void print(const vector<T>& vrr); // print vector of T
/*
Main function
*/
int main() {

    int arr[]={1,2,2,2,1,1};
    vector<int> vrr(arr,arr+5);
    vector<int>::iterator pt1;
    cout<<"The original vector:"<<endl;
    print(vrr);
    // unique
	cout<<"-------------------------------------------------------"<<endl;
    pt1=unique(vrr.begin(),vrr.end());
    cout<<"The modified vector:"<<endl;
    vrr.resize(pt1-vrr.begin()+1);
    print(vrr);
}
/*
Function definition
*/
template <class T>
void print(const vector<T>& vrr){
	typename vector<T>::const_iterator it;
	cout<<"{";
	for(it=vrr.begin();it!=vrr.end();++it){
		cout<<setw(2)<<*it;
		if (it!=vrr.end()-1) cout<<",";
	}
	cout<<"}"<<endl;
}


The output is:
The original vector:
{ 1, 2, 2, 2, 1}
-------------------------------------------------------
The modified vector:
{ 1, 2, 1, 2}

Actually, it is not as expected. I think the expected result must be:
{1,2,1}.

I would be very appreciated if you can explain to me the reason of this strangeness.

Thank you.
Last edited on
The right way to do std::unique is:

1. first std::sort the container - because std::unique checks two consecutive elements for equivalence; if you have two equivalent elements that are not consecutive, the latter won’t be removed.
2. then std:: unique
3. finally std::erase because std::unique doesn't actually remove the elements, instead they are copied to the end

http://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector
You can use std::set to filter out the duplicate values.
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
#include <iostream>
#include <vector>
#include <set>

using namespace std;

void print(const vector<int> &vrr);

int main() 
{
	int i;
	int arr[] = {1,2,2,2,1,1};
	vector<int> vrr(arr, arr+5);

	cout << "The original vector : "; print(vrr);

	set<int> vrr_unique;
	for(i = 0; i < vrr.size(); i++) vrr_unique.insert(vrr[i]);

	vrr.clear(); 
	for(set<int>::iterator it = vrr_unique.begin(); it != vrr_unique.end(); it++) vrr.push_back(*it);

	cout << "The result vector : "; print(vrr);

	return 0;
}

void print(const vector<int> &vrr)
{
	int i;
	for(i = 0; i < vrr.size(); i++)
	{
		cout << vrr[i]; 
		if(i != vrr.size() - 1) cout << ", ";
	}
	cout << endl;
}


The original vector : 1, 2, 2, 2, 1
The result vector : 1, 2

http://cpp.sh/3rzva
Last edited on
Thank you for you explanations. I've got the point: The return value is
An iterator to the element that follows the last element not removed.
The range between first and this iterator includes all the elements in the sequence that were not considered duplicates.
.

Therefore I the resize() member function I should have set pt1-vrr.begin() instead of pt1-vrr.begin()+1. Using distance(vrr.begin(),pt1) is also an option for it.

Best regards!
OP: Did you try out first what you've just proposed? I don't think so, otherwise you'd have seen that the modified vector is now {1, 2, 1}.
You'd either have to use a set as Handoro said or sort the vector first as I did
Yes. I tried the following code:
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
#include <iostream>
#include <iomanip>
#include <algorithm> //unique
#include <vector>
using namespace std;
/*
Function declaration
*/
template <class T>
void print(const vector<T>& vrr); // print vector of T
/*
Main function
*/
int main() {

    int arr[]={1,2,2,2,1,1};
    vector<int> vrr(arr,arr+5);
    vector<int>::iterator pt1;
    cout<<"The original vector:"<<endl;
    print(vrr);
    // unique
	cout<<"-------------------------------------------------------"<<endl;
    pt1=unique(vrr.begin(),vrr.end());
    cout<<"The modified vector:"<<endl;
    vrr.resize(pt1-vrr.begin());
    print(vrr);
}
/*
Function definition
*/
template <class T>
void print(const vector<T>& vrr){
	typename vector<T>::const_iterator it;
	cout<<"{";
	for(it=vrr.begin();it!=vrr.end();++it){
		cout<<setw(2)<<*it;
		if (it!=vrr.end()-1) cout<<",";
	}
	cout<<"}"<<endl;
}


And the output is what I expected:


The original vector:
{ 1, 2, 2, 2, 1}
-------------------------------------------------------
The modified vector:
{ 1, 2, 1}


The unique operation will work by the following sequence:
{ 1, 2, 2, 2, 1}
-> { 1, 2, 2, 2, 1}
-> { 1, 2, 2, 1}
-> { 1, 2, 1}

Thank you.
Topic archived. No new replies allowed.