C++按值而不是按位置擦除向量元素?

Jak*_*son 235 c++ stl vector erase erase-remove-idiom

vector<int> myVector;
Run Code Online (Sandbox Code Playgroud)

并且让我们说向量中的值是这个(按此顺序):

5 9 2 8 0 7
Run Code Online (Sandbox Code Playgroud)

如果我想删除包含值"8"的元素,我想我会这样做:

myVector.erase(myVector.begin()+4);
Run Code Online (Sandbox Code Playgroud)

因为那会抹掉第4个元素.但有没有办法根据值"8"擦除元素?喜欢:

myVector.eraseElementWhoseValueIs(8);
Run Code Online (Sandbox Code Playgroud)

或者我只是需要遍历所有的向量元素并测试它们的值?

Geo*_*che 390

std::remove()相反怎么样:

#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());
Run Code Online (Sandbox Code Playgroud)

这种组合也称为擦除 - 删除习语.

  • 为了使用remove()函数,你必须`#include <algorithm>`.否则它会给你一个疯狂的错误.请添加回答. (32认同)
  • @GeorgFritzsche为什么你不能回答他的问题,而不是给他发一个链接?是的,是O(n) (12认同)
  • @jak:看一下`remove()`的描述:它移动所有值不等于传递给`[begin,end)`范围开头的值.在你的问题中你的例子你会得到'5,9,2,0,7,7`.因为`remove()`然后将迭代器返回到新的结尾,`vec.erase()`可以删除过时的元素(即第二个`7`),如果需要的话. (10认同)
  • 链接到的文档页面为您提供该信息. (5认同)
  • 该算法的愚蠢之处在于,当找到第一个匹配项时,remove 不会停止。不断比较列表的其余部分是低效的。因此,如果向量中可能存在相同值的多个副本,那么这很好,但对于唯一值向量的常见情况来说,这并不是一个好的答案。在这种情况下, std::find 是更好的选择。 (5认同)
  • @Assimilater:没有必要. (3认同)
  • 我有点困惑......看起来这会从我想要擦除的元素中删除矢量中的元素,一直到矢量的末尾......我不正确吗?我只想删除一个元素. (2认同)
  • 这个程序的复杂程度如何?在) ??? (2认同)
  • @shane记录了“ erase()”和“ remove()”的复杂性,例如参见[cppreference](http://en.cppreference.com/w/)。 (2认同)
  • @AlisherKassymov因为在这里很容易找到答案。这是一种更好的学习方法。不同的人有不同的方法,值得尊重。 (2认同)

zne*_*eak 92

您可以使用std::find获取值的迭代器:

#include <algorithm>
std::vector<int>::iterator position = std::find(myVector.begin(), myVector.end(), 8);
if (position != myVector.end()) // == myVector.end() means the element was not found
    myVector.erase(position);
Run Code Online (Sandbox Code Playgroud)

  • 如果您只期望出现该值,那么这很好. (12认同)
  • @TomášZato:或者只想删除一个,这似乎是这个问题的情况. (6认同)
  • 为了删除所有值,初始化`position = myVector.begin()`并将所有内容封装在`while(position!= myVector.end())`循环中 (2认同)

Nav*_*een 11

你不能直接这样做.您需要使用std::remove算法将要擦除的元素移动到向量的末尾,然后使用erase函数.像:myVector.erase(std::remove(myVector.begin(), myVector.end(), 8), myVec.end());.有关详细信息,请参阅vector中的擦除元素.