Удаление всех пустых элементов в векторе с конца

Учитывая std::vector из строк, каков наилучший способ удаления всех элементов, начиная с конца, которые являются пустыми (равно пустой строке или пробелу). Удаление элементов должно прекратиться, когда будет найден непустой элемент.

Мой текущий метод (работа в процессе) что-то вроде:

while (Vec.size() > 0 && (Vec.back().size() == 0 || is_whitespace(Vec.back()))
{
    Vec.pop_back();
}

где is_whitespace возвращает bool, указывающий, является ли строка пробелом или нет

Я подозреваю, что мой метод будет изменять размер вектора на каждой итерации, и это неоптимально. Может быть, с некоторым алгоритмом это можно сделать за один шаг.

Ввод: { "A", "B", " ", "D", "E", " ", "", " " }}

Желаемый результат: { "A", "B", " ", "D", "E" }

2 ответа

Поскольку я не нашел хорошего на первый взгляд дурака, вот простое решение:

// 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));

Обратите внимание unsigned в лямбде из-за этого гоча.

Живой пример благодаря Killzone Kid.

Вот лучший способ:

for (auto it = Vec.rbegin(); it != Vec.rend() && is_whitespace(*it); )
{
    it = Vec.erase(it);
}

Он начнется с конца и остановится, как только встретится непробельный символ или будет достигнут вектор начала, в зависимости от того, что наступит раньше. Обратите внимание, что я не увеличиваю итератор в for петля.

Другие вопросы по тегам