如何从具有特定值的stl向量中删除项?

bra*_*ray 135 c++ stl

我正在查看stl向量的API文档,并注意到vector类上没有允许删除具有特定值的元素的方法.这看起来像是一个常见的操作,似乎很奇怪,没有内置的方法来做到这一点.

Jim*_*uck 157

std::remove实际上并没有从容器中擦除元素,但它确实返回了新的结束迭代器,可以将其传递给container_type::eraseREAL以删除现在位于容器末尾的额外元素:

std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());
Run Code Online (Sandbox Code Playgroud)

  • 这是删除文件的`remove`版本.你需要包含`<algorithm>`才能访问处理容器的`remove`版本. (14认同)
  • `vec.end()`确实需要相同,但这没关系,因为`std :: remove`不会改变它.如果确实改变它(并使旧值无效)那么就会出现问题:参数的评估顺序是未指定的,因此你不知道第二个`vec.end()`是否仍然有效.用过的.它的原因很简单,`std :: remove`不会改变容器的大小,只是移动内容. (8认同)
  • 这种一对一语句形式是否取决于编译器评估参数的顺序,或者`vec.end()`是否保证在调用`std :: remove`的任何一侧都是相同的?在我阅读网络的其他部分时,我认为这是安全的,但应该明确说明. (3认同)
  • 我发现这个问题很重要,因为我有同样的问题.但是,我的visual studio只用一个参数来获取`std :: remove`; 那就是`const char*_Filename`.我需要用什么方法打电话? (2认同)

Eth*_*one 59

如果你想删除项目,下面会有多一点的效率.

std::vector<int> v;


auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
    v.erase(it);
Run Code Online (Sandbox Code Playgroud)

或者,如果订单对您无关紧要,您可以避免搬运物品的开销:

std::vector<int> v;

auto it = std::find(v.begin(), v.end(), 5);

if (it != v.end()) {
  using std::swap;

  // swap the one to be removed with the last element
  // and remove the item at the end of the container
  // to prevent moving all items after '5' by one
  swap(*it, v.back());
  v.pop_back();
}
Run Code Online (Sandbox Code Playgroud)

  • 注意,如果存在重复项,则不会删除重复项,而std :: remove_if方法会删除重复项。 (2认同)

bra*_*ray 15

使用带有begin和end迭代器的全局方法std :: remove,然后使用std :: vector.erase实际删除元素.

文档链接
std :: remove http://www.cppreference.com/cppalgorithm/remove.html
std :: vector.erase http://www.cppreference.com/cppvector/erase.html

std::vector<int> v;
v.push_back(1);
v.push_back(2);

//Vector should contain the elements 1, 2

//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);

//Erase the "removed" elements.
v.erase(newEnd, v.end());

//Vector should now only contain 2
Run Code Online (Sandbox Code Playgroud)

感谢Jim Buck指出我的错误.


Pav*_*aka 15

c++20开始:

引入了非成员函数std::erase,它将要删除的向量和值作为输入。

前任:

std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
Run Code Online (Sandbox Code Playgroud)

  • 不仅如此,每个特定容器都超载了! (2认同)

Xav*_*det 5

另请参阅std::remove_if以便能够使用谓词...

这是上面链接中的示例:

vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 4 2 8 5 7"

vector<int>::iterator new_end = 
    remove_if(V.begin(), V.end(), 
              compose1(bind2nd(equal_to<int>(), 0),
                       bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 5 7".
Run Code Online (Sandbox Code Playgroud)

  • 请在这篇文章中添加更多详细信息。就目前情况而言,其大部分内容来自链接,如果链接断开,就会丢失。 (2认同)

nsa*_*ers 5

如果您有未排序的向量,则只需与最后一个向量元素交换即可resize()

使用订购的容器,您将获得最好的选择?std::vector::erase()。请注意,中有一个std::remove()定义<algorithm>,但实际上并没有进行擦除。(请仔细阅读文档)。


Luk*_*ell 5

其他答案涵盖了如何做到这一点,但我想我也要指出,向量API中没有这个并不奇怪:在向量中线性搜索效率低下的值,然后是一堆复制将其删除。

如果您正在密集地执行此操作,则出于此原因,值得考虑使用std :: set。