вектор c ++;remove_if удаляет только одно значение? - PullRequest
1 голос
/ 11 октября 2011

Я должен реализовать функцию, которая стирает диапазон значений из контейнеров. Итак

eraseRange(v, 1.5, 24);
Например,

удалит любое значение больше 1,5 и меньше 24 из контейнера v. И моя функция отлично работает для списков, где я использую:

container.erase(remove_if(container.begin(), container.end(), rg));

Где rg проверяет, находится ли он в пределах диапазона (реализация этой части не является проблемой, поэтому я не буду останавливаться на этом).

Однако при вызове eraseRange для вектора и использовании аналогичного метода для удаления значений стирается только самое первое значение. Так что, если бы у меня был вектор с номерами от 1 до 10, и я бы позвонил:

eraseRange(v, 3, 7);

Только 3 удаляется.

Теперь это обычно не проблема, я бы просто использовал итератор для проверки значений. За исключением этого конкретного упражнения, петли для / while / do явно запрещены ...

Таким образом, проблема, похоже, связана с контейнерами, которые имеют итераторы произвольного доступа. И я не уверен, что реализовать в качестве альтернативы. Помощь

Ответы [ 2 ]

10 голосов
/ 11 октября 2011

Существует несколько перегрузок erase.

Одна перегрузка, которую вы используете, занимает один итератор и стирает элемент, на который указывает итератор.

Другая перегрузка, который вы должны использовать, берет диапазон (пару итераторов) и стирает все элементы в диапазоне:

c.erase(remove_if(c.begin(), c.end(), rg), c.end());
                                         ^^^^^^^^^

[Я не уверен, почему ваш код "отлично работает для списков," как ты говоришь;std::list имеет те же две перегрузки, что и erase.Обратите внимание, что std::list также имеет функцию-член remove_if, которая обеспечивает лучшую реализацию алгоритма стирания / удаления, специально оптимизированного для std::list (поскольку std::list реализован в виде связанного списка, он может реализовывать удаление / удалениебез фактического перемещения каких-либо объектов).]

1 голос
/ 11 октября 2011

remove_if возвращает один итератор для "new last". То есть перемешивается все, удовлетворяющее вашему предикату, чтобы пройти новую последнюю в векторе. Все до нового последнего не удовлетворяет вашему предикату, в то время как все прошлое делает это. Поскольку вы выполняете erase только для одного элемента из вектора, вы удаляете только последний последний элемент - это единственное, что удовлетворяет вашему предикату. Вместо этого вы хотите стереть все с нового последнего -> конца, то есть всего, что удовлетворило ваш предикат

container.erase(
   remove_if(container.begin(), container.end(), rg), 
   container.end()
 );
...