如何在排序的向量上正确应用擦除删除习惯用法?

时间:2014-04-24 13:34:53

标签: c++ vector stl

通常,我们希望应用erase remove idiom来正确地消除向量中的元素,例如:

v.erase( std::remove( std::begin(v), std::end(v), 5 ), std::end(v) ); 

其中v是整数向量。

但是如果矢量先排序怎么办?以下是否会做同样的事情,如果是,那么它是最优化的方式吗?

std::sort(v.begin(), v.end());

IntegerVector::iterator it = std::lower_bound(v.begin(), v.end(), 5);

if(it != v.end()) {
    (void)v.erase(it, v.end());
}

这是否正确应用了删除删除习惯用法?在删除过程后,矢量是否仍然排序(我假设它是)?我们不需要做这样的事情:

(void)v.erase(std::remove(it), v.end());

(std :: remove的语法不正确,但希望你明白了。)

谢谢,

本。

3 个答案:

答案 0 :(得分:4)

您可以使用:

auto range = std::equal_range(std::begin(v), std::end(v), 5);
v.erase(range.first, range.second);

对于C ++ 03,您必须将auto替换为(详细)std::pair<IntegerVector::iterator, IntegerVector::iterator>

std::equal_range返回一对迭代器,其中范围[first, second)的值等于给定值(此处为5)(假设v已排序)。

答案 1 :(得分:1)

这不再是删除删除的习惯用语,但是,是的,它将正确,最佳和稳定地完成工作。

std::remove在删除之前将所有不需要的元素收集到一个连续的块中,但是你的排序已经完成,所以不需要它。

您可以删除无意义的(void)前缀。

答案 2 :(得分:1)

假设您要删除所有等于5的元素,请确保您的代码不正确。 这是更正后的版本:

std::sort(v.begin(), v.end());

auto lower = std::lower_bound(v.begin(), v.end(), 5);

if(lower != v.end()) {
  auto upper = std::upper_bound(lower,v.end(), 5);
  v.erase(lower,upper);
}