Sturm
Sturm

Reputation: 4125

Removing all empty elements in a vector from end

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" }

Upvotes: 3

Views: 2774

Answers (2)

Baum mit Augen
Baum mit Augen

Reputation: 50063

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.

Upvotes: 5

Mike Borkland
Mike Borkland

Reputation: 745

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.

Upvotes: 4

Related Questions