In C++, std::unique is used to remove duplicates of any element present consecutively in a range[first, last). It performs this task for all the sub-groups present in the range having the same element present consecutively.
- It does not delete all the duplicate elements, but it removes duplicacy by just replacing those elements with the next element present in the sequence which is not duplicate to the current element being replaced. All the elements which are replaced are left in an unspecified state.
- Another interesting feature of this function is that it does not change the size of the container after deleting the elements, it just returns a pointer pointing to the new end of the container, and based on that we have to resize the container or remove the garbage elements.
Time Complexity: O(N)
Space Complexity: O(1)
Usage of std::unique in C++
The std::unique can be used in two ways as shown below:
- For Comparing elements using ==
- For Comparing using a pre-defined function
1. Comparing elements using ==:
Syntax:
ForwardIterator unique (ForwardIterator first, ForwardIterator last, BinaryPredicate Pred);
Here, the first and last are the same as the previous case.
Pred: Binary function that accepts two elements in the range as argument, and returns a value convertible to bool. The value returned indicates whether both arguments are considered equivalent(if true, they are equivalent and one of them is removed). The function shall not modify any of its arguments. This can either be a function pointer or a function object.
Return Value: It returns an iterator to the element that follows the last element not removed. The range between the first and this iterator includes all the elements in the sequence that were not duplicates and hence not removed.
Below is the implementation of the above method:
C++
// C++ program to demonstrate the use of std::unique
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = { 1, 1, 3, 3, 3, 10, 1, 3, 3, 7, 7, 8 };
vector<int>::iterator ip;
// Using std::unique
ip = std::unique(v.begin(), v.begin() + 12);
// Now v becomes {1 3 10 1 3 7 8 * * * * *}
// * means undefined
// Resizing the vector so as to remove the undefined
// terms
v.resize(std::distance(v.begin(), ip));
// Displaying the vector after applying std::unique
for (ip = v.begin(); ip != v.end(); ++ip) {
cout << *ip << " ";
}
return 0;
}
Here, in this vector, all the sub-groups having consecutive duplicate elements has been reduced to only one element. Note that it doesnot matter whether the same element is present later on as well, only duplicate elements present consecutively are handled by this function.
2. Comparing using a pre-defined function:
Syntax:
ForwardIterator unique (ForwardIterator first, ForwardIterator last);
first: Forward iterator to the first element in the container.
last: forward iterator to the last element in the container.
Return Value: It returns 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 duplicates and hence not removed.
Below is the implementation of the above method:
C++
// C++ program to demonstrate the use of std::unique
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
// Defining the BinaryFunction
bool Pred(char a, char b)
{
// Checking if both the arguments are same and equal
// to 'G' then only they are considered same
// and duplicates are removed
if (a == b && a == 'G') {
return 1;
}
else {
return 0;
}
}
int main()
{
// Declaring a string
string s = "You arre vvvisiting GGGGFGGGG";
// Using std::unique to remove the consecutive
// G in the word
auto ip = std::unique(s.begin(), s.end(), Pred);
// Displaying the corrected string
cout << string(s.begin(), ip);
return 0;
}
OutputYou arre vvvisiting GFG
Here, we have manipulated the binary function in such a way that only if two G are passed as arguments, then only they will be considered as same, and if any other character is present consecutively, then it will remain unaffected, and will not be removed (like r in arre, v in visiting).
Interesting Point:
The std::unique function can be used in combination with the std::erase function to remove consecutive duplicate elements from a sorted container.
vec.erase(unique(vec.begin(), vec.end()), vec.end());
Where std::unique can be used?
1. Remove all the duplicate elements from a container:
Many of you must have searched for std::unique with a view that it will remove all the duplicate elements from the container, and now you might feel a bit disappointed to know that it removes only the consecutive duplicate elements. But, although, std::unique cannot do so as per its definition, but applying a bit of logic, we can make that happen. What we need to do is just sort the array before applying std::unique, such that all equal elements become consecutive, and now we have std::unique to remove all the duplicate consecutive elements. So, std::unique can also be used to remove all the duplicate elements from a container.
Below is the implementation of the above method:
C++
// C++ program to demonstrate the use of std::unique
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = { 1, 2, 3, 3, 3, 10, 1, 2, 3, 7, 7, 8 };
vector<int>::iterator ip;
// Sorting the array
std::sort(v.begin(), v.end());
// Now v becomes 1 1 2 2 3 3 3 3 7 7 8 10
// Using std::unique
ip = std::unique(v.begin(), v.begin() + 12);
// Now v becomes {1 2 3 7 8 10 * * * * * *}
// * means undefined
// Resizing the vector so as to remove the undefined
// terms
v.resize(std::distance(v.begin(), ip));
// Displaying the vector after applying std::unique
for (ip = v.begin(); ip != v.end(); ++ip) {
cout << *ip << " ";
}
return 0;
}
Explanation:
Firstly, we sorted the array such that all the equal duplicate elements become consecutive and now applying std::unique to it such that the duplicacy is removed, and in this way we remove all the duplicate elements from a container, whether consecutive or not.
Count unique elements: It can also be used if we want to count the total no. of unique elements in a container.
C++
// C++ program to demonstrate the use of std::unique
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
vector<int> v = { 1, 1, 3, 3, 3, 10, 1, 3, 3, 7, 7, 8 };
vector<int>::iterator ip;
int count;
sort(v.begin(), v.end());
// Using std::unique and std::distance to count
// unique elements in a container
count = std::distance(
v.begin(), std::unique(v.begin(), v.begin() + 12));
// Displaying the value of count
cout << "Total no. of unique elements = " << count;
return 0;
}
OutputTotal no. of unique elements = 5
Explanation:
As we know that std::unique returns an iterator to what should be the new end of the container after removing duplicate elements, so just counting the total no. of elements from beginning till this new end with the help of std::distance, should give us the total no. of unique elements in the container.
Similar Reads
Unique_ptr in C++
In C++, unique_ptr is a smart pointer that manages a dynamically allocated object, and it was introduced in C++11. It is defined in the <memory> header file. Here are the key points about unique_ptr:Ownership: unique_ptr owns the object it points to. Only one unique_ptr can own an object at a
4 min read
std::unique_copy in C++
std::unique is used to remove duplicates of any element present consecutively in a range[first, last). It performs this task for all the sub-groups present in the range having the same element present consecutively. But, what if we don't want to alter with the original range and just want the result
6 min read
std::make_unique in C++ 14
std::make_unique is a utility function in C++ that was introduced in C++14. It is used to create a unique_ptr object, which is a smart pointer that manages the lifetime of dynamically allocated objects. It is defined inside <memory> header file. Syntaxstd::make_unique <object_type> (argu
2 min read
forward_list::unique() in C++ STL
forward_list::unique() is an inbuilt function in C++ STL which removes all consecutive duplicate elements from the forward_list. It uses binary predicate for comparison. Syntax: forwardlist_name.unique(BinaryPredicate name)Parameters: The function accepts a single parameter which is a binary predica
2 min read
std::strncmp() in C++
std::strncmp() function in C++ lexicographically compares not more than count characters from the two null-terminated strings and returns an integer based on the outcome. This function is a Standard Library function that is defined in <cstring> header file in C++.Syntaxint strncmp(const char *
5 min read
set::size() in C++ STL
In C++, set::size() function is a built-in used to find the number of elements in the given set container. It is the member function of std::set class defined inside <set> header file. In this article, we will learn about the std::set::size() method in C++.Example:C++// C++ Program to illustra
2 min read
std::variant in C++ 17
In the world of modern C++ programming, the std::variant is a powerful tool that allows you to work with multiple data types in a flexible and type-safe manner. In this article, we will discuss std::variant and explore its fundamentals, applications, and benefits with practical code examples. Prereq
4 min read
Unordered Map in C++ STL
In C++, unordered_map is an unordered associative container that stores data in the form of unique key-value pairs. But unlike map, unordered map stores its elements using hashing. This provides average constant-time complexity O(1) for search, insert, and delete operations but the elements are not
7 min read
Set in C++ STL
In C++, sets are associative container which stores unique elements in some sorted order. By default, it is sorted ascending order of the keys, but this can be changed as per requirement. It provides fast insertion, deletion and search operations.Example: C++#include <iostream> #include <se
7 min read
Unordered Sets in C++ STL
In C++, unordered_set is an unordered associative container that stores unique elements. Unlike set, it stores its elements using hashing. This provides average constant-time O(1) search, insert, and delete operations but the elements are not sorted in any particular order.Example:C++#include <io
6 min read