Given a std::vector
of strings, what is the best way of removing all elements starting from the end that are empty (equal to empty string or whitespace). The removal of elements should stop when a non-empty element is found.
My current method, (work in progress) is something like:
while (Vec.size() > 0 && (Vec.back().size() == 0 || is_whitespace(Vec.back()))
{
Vec.pop_back();
}
where is_whitespace
returns a bool stating if a string is whitespace or not
I suspect that my method will resize the vector at each iteration and that is suboptimal. Maybe with some algorithm it is possible to do in one step.
Input: { "A", "B", " ", "D", "E", " ", "", " " }
Desired Output: { "A", "B", " ", "D", "E" }
As I did not find a good dupe on first glance, here is a simple solution:
// Helper function to see if string is all whitespace
// Can also be implemented as free-function for readablity and
// reusability of course
auto stringIsWhitespace = [](const auto &str)
{
return std::all_of(
begin(str), end(str), [](unsigned char c) { return std::isspace(c); });
};
// Find first non-whitespace string from the back
auto it = std::find_if_not(rbegin(Vec), rend(Vec), stringIsWhitespace);
// Erase from there to the end
Vec.erase(it.base(), end(Vec));
Note the unsigned
in the lambda due to this gotcha.
Live example thanks to @Killzone Kid.
Here's a better way:
for (auto it = Vec.rbegin(); it != Vec.rend() && is_whitespace(*it); )
{
it = Vec.erase(it);
}
It will start from the end and stop once non-whitespace has been encountered or the beginning of the vector is reached, whichever comes first. Note that I don't increment the iterator in the for
loop.