Reputation: 5068
Perhaps anyone have an efficient way to remove consecutive duplications of specific characters preferably using built-in string operations, and without explicitly going through the string characters.
For example, when I have wildcard pattern and I'd like to remove consecutive asterisks only (*
)
/aaaa/***/bbbb/ccc/aa/*****/dd --> /aaaa/*/bbbb/ccc/aa/*/dd
For all characters repetitive duplications I can use std::unique
in the following manner :
str.erase( std::unique(str.begin(), str.end()), str.end());
but what about specific chars only.
Upvotes: 4
Views: 256
Reputation: 311010
You can use the same algorithm std::unique
with a lambda expression.
For example
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
int main()
{
std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd";
char c = '*';
s.erase( std::unique( std::begin( s ), std::end( s ),
[=]( const auto &c1, const auto &c2 ) { return c1 == c && c1 == c2; } ),
std::end( s ) );
std::cout << s << '\n';
}
The program output is
/aaaa/*/bbbb/ccc/aa/*/dd
Or you can remove a set of duplicate characters. For example
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
#include <cstring>
int main()
{
std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd";
const char *targets = "*b";
auto remove_chars = [=]( const auto &c1, const auto &c2 )
{
return strchr( targets, c1 ) && c1 == c2;
};
s.erase( std::unique( std::begin( s ), std::end( s ), remove_chars ),
std::end( s ) );
std::cout << s << '\n';
}
The program output is
/aaaa/*/b/ccc/aa/*/dd
In the last example I suppose that the character '\0'
is not included in the string. Otherwise you have to add one more subexpression to the logical expression in the lambda.
Upvotes: 9