Given a string:
std::string str{"This i_s A stRIng"};
Is it possible to transform it to lowercase and remove all non-alpha characters in a single pass?
Expected result:
this is a string
I know you can use std::transform(..., ::tolower) and string.erase(remove_if()) combination to make two passes, or it can be done manually by iterating each character, but is there a way to do something that would combine the std::transform and erase calls without having to run through the string multiple times?
C++20 ranges allow algorithms to be combined, in a one-pass fashion.
std::string str{"This i_s A stRIng"};
std::string out;
auto is_alpha_or_space = [](unsigned char c){ return isalpha(c) || isspace(c); };
auto safe_tolower = [](unsigned char c){ return tolower(c); };
std::ranges::copy( str
| std::views::filter(is_alpha_or_space)
| std::views::transform(safe_tolower)
, std::back_inserter(out));
See it on Compiler Explorer
First let me notice that you seem to want to filter alphabetic characters or spaces, that is, characters l for which std::isalpha(l) || std::isspace(l) returns true.
Assuming this, you can achieve what you want using std::accumulate
str = std::accumulate(str.begin(), str.end(), std::string{},
[](const std::string& s, const auto& l) {
if (std::isalpha(l, std::locale()) || std::isspace(l, std::locale()))
return s + std::tolower(l, std::locale());
else
return s;
});
See it Live on Coliru.
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