Removing duplicate characters from string using STL
The whole point of C++’ algorithm and container design is that the algorithms are – as far as possible – container agnostic.
So the same algorithm that works on vectors works – of course! – on strings.
std::sort(str.begin(), str.end());
str.erase(std::unique(str.begin(), str.end()), str.end());
The same even works on old-style C strings – with the small difference that you cannot erase
their tails, you need to manually truncate them by re-setting the null terminating character (and there are no begin
and end
member functions so you’d use pointers to the first and one-past-last character).
Remove all duplicate characters from a string (STL)
Solution simple as always:
void RemoveDuplicates (std::string& input) {
std::string::iterator it = std::unique(input.begin(), input.end());
input.erase(it, input.end());
std::cout << "New input = "<< input << std::endl;
}
Another solution to return a new string:
std::string RemoveDuplicates (const std::string& input) {
std::string newT(input);
std::string::iterator it = std::unique(newT.begin(), newT.end());
newT.erase(it, newT.end());
return newT;
}
If desired result is hello -> helo then the solution is :
std::string RemoveDuplicates (const std::string& input) {
std::string newInput;
const char * prev = nullptr;
for (const auto & ch : input) {
if (!prev || (*prev != ch)) {
newInput.push_back(ch);
}
prev = &ch;
}
return newInput;
}
If you need to save order of chars and remove duplicates:
std::string RemoveDuplicates (const std::string& input) {
std::string newInput;
std::set<char> addedChars;
for (const auto & ch : input) {
if (addedChars.end() == addedChars.find(ch)) {
newInput.push_back(ch);
addedChars.insert(ch);
}
}
return newInput;
}
For strings, how do I remove repeated characters?
You can code it like this using the built in methods:
s.erase(std::unique(s.begin(), s.end()), s.end());
Deleting Duplicate chars from a string
Change your duplicate function to this
string deduplicate(string input){
int i;
int x;
int len= input.length();
string outputStr;
string strEmpty = "Empty";
if (input.length() == 1)
{return input;}
for(i = 0; i<len;i++){
for(x = i+1; x<input.length(); x++){ // This line
if(input[i] == input[x]){
input.erase(x,1);
input.erase(i,1); // and this line
x--;
}
}
len = input.length();
}
return outputStr = input;
if (input.length() == 0)
{return strEmpty;}
return outputStr = input;
}
You did delete the duplicate character but not original, so the second erase statement does it.
Remove duplicates from the string in CPP
So, after doing a bit of reading on the Internet I realized that I was trying to return a pointer to the local array in the removeDuplicates()
function.
This is what works fine
#include <bits/stdc++.h>
using namespace std;
void removeDuplicates(string &s,int n){
vector<char> vec;
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
vec.push_back(s[i]);
exists[s[i]]++;
}
}
for(auto x: vec)
cout << x;
}
//driver code
int main(){
string str;
cin >> str;
removeDuplicates(str,str.length());
return 0;
}
PS: We can make the return type of function to vector as well.
Remove duplicates in string algorithm
Your loops could look the following way
#include <iostream>
#include <string>
int main()
{
std::string s = "Blah blah...";
std::cout << '\"' << s << '\"' << std::endl;
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
std::string::size_type j = i + 1;
while ( j < s.size() )
{
if ( s[i] == s[j] )
{
s.erase( j, 1 );
}
else
{
++j;
}
}
}
std::cout << '\"' << s << '\"' << std::endl;
return 0;
}
The output is
"Blah blah..."
"Blah b."
There are many other approaches using standard algorithms. For example
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main()
{
std::string s = "Blah blah...";
std::cout << '\"' << s << '\"' << std::endl;
auto last = s.end();
for ( auto first = s.begin(); first != last; ++first )
{
last = std::remove( std::next( first ), last, *first );
}
s.erase( last, s.end() );
std::cout << '\"' << s << '\"' << std::endl;
return 0;
}
The output is the same as for the previous code example
"Blah blah..."
"Blah b."
Removing duplicates in a vector of strings
#include <algorithm>
template <typename T>
void remove_duplicates(std::vector<T>& vec)
{
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
}
Note: this require that T has operator<
and operator==
defined.
Why it work?
std::sort sort the elements using their less-than comparison operator
std::unique removes the duplicate consecutive elements, comparing them using their equal comparison operator
What if i want only the unique elements?
Then you better use std::map
#include <algorithm>
#include <map>
template <typename T>
void unique_elements(std::vector<T>& vec)
{
std::map<T, int> m;
for(auto p : vec) ++m[p];
vec.erase(transform_if(m.begin(), m.end(), vec.begin(),
[](std::pair<T,int> const& p) {return p.first;},
[](std::pair<T,int> const& p) {return p.second==1;}),
vec.end());
}
See: here.
Related Topics
Print Out All Combinations of Index
Why Is Copy Constructor Not Being Called in This Code
Why Does Std::Vector Work with Incomplete Types in Class Definitions
Is Lambdification of a Concept an Improvement or Bad Practice
How to Keep My Topmost Window on Top
Trying to Use a While Statement to Validate User Input C++
Format Curly Braces on Same Line in C++ VScode
What Is the Size of Sizeof(Vector)? C++
Another Bug in G++/Clang? [C++ Templates Are Fun]
How to Change Directshow Filter Properties C++
How to Compare Char Variables (C-Strings)
Undefined Reference to Template Members
How to Force the Use of Cmov in Gcc and VS
Wait for Input for a Certain Time
Undefined Behavior in C/C++: I++ + ++I VS ++I + I++