Удаление всех пустых элементов в векторе с конца
Учитывая 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
петля.