2009-03-14 1 views

ответ

21

Я предпочитаю remove_if

v.erase(remove_if(v.begin(), v.end(), 
       mem_fun_ref(&MyClass::isTiredOfLife)), 
     v.end()); 

remove_if возвращает итератор, указывающий после последнего элемента, который по-прежнему в последовательности. erase стирает все от первого до последнего аргумента (оба итератора).

+1

Я забыл о remove_if() +1 , –

+0

Очень круто. Никогда не видел этого раньше. +1 – Bernard

+0

Спасибо, что сделал трюк. –

6

Использование remove_if - это «правильный» способ сделать это. Будьте осторожны, чтобы не использовать итератор для циклического перехода и удаления, поскольку удаление элементов делает недействительным итератор. Фактически, любой пример, который использует erase() в качестве основного метода, является плохой идеей для векторов, потому что erase - это O (n), что сделает ваш алгоритм O (n^2). Это должен быть алгоритм O (n).

Метод, который я даю ниже, скорее всего будет быстрее, чем remove_if, но, в отличие от remove_if, НЕ сохранит относительный порядок элементов. Если вы заботитесь о поддержании порядка (т. Е. Ваш вектор отсортирован), используйте remove_if, как в ответе выше. Если вы не заботитесь о порядке, и если количество элементов, которые необходимо удалить, как правило, меньше, чем четверть вектора, этот метод, вероятно, будет быстрее:

for(size_t i = 0; i < vec.size();) 
    if(vec[i].isTiredOfLife()) 
    { 
     vec[i] = vec.back(); 
     vec.pop_back(); 
    } 
    else 
     ++i; 
+0

D'oh. Я забыл об этом. Он даже выделен жирным шрифтом на странице, с которой я связан. : o Я удалил свой пост, поэтому никто его не использует. – Bernard

+0

Не будет ли это переупорядочивать элементы в векторе? Предполагая, что, например, вектор ввода отсортирован, выходной вектор не будет, последний элемент займет позицию первого удаленного элемента. –

+0

Возможно, вы захотите обновить свой ответ, чтобы больше не ссылаться на Бернарда. –