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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With