【问题标题】:C++ Erase vector element by value rather than by position? [duplicate]C ++按值而不是按位置擦除矢量元素? [复制]
【发布时间】:2023-04-04 08:46:01
【问题描述】:
vector<int> myVector;

假设向量中的值是这样的(按此顺序):

5 9 2 8 0 7

如果我想擦除包含“8”值的元素,我想我会这样做:

myVector.erase(myVector.begin()+4);

因为那会删除第 4 个元素。但是有没有办法根据值“8”擦除元素?喜欢:

myVector.eraseElementWhoseValueIs(8);

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

【问题讨论】:

  • @BenVoigt:你的问题很自大——显然这个人无法回答,你应该做的是创建一个涵盖你提到的所有案例的答案。
  • @slashmais:哦,废话,我的澄清问题很简单,不需要专业的程序员来回答。而且我无法涵盖“你想做什么?”的所有可能值。对于所有三种情况。仅针对“没有匹配元素”的情况,可能的行为包括“无”、“抛出异常”、“返回错误”、“退出进程(可能通过assert())”、“向std::cerr 发送消息“......甚至那些也不是详尽无遗的。不,提问者需要说明错误处理策略,即使没有找到匹配项也是错误。
  • ... QED 案例。我认为

标签: c++ vector stl erase erase-remove-idiom


【解决方案1】:

std::remove() 怎么样:

#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());

这种组合也称为erase-remove idiom

【讨论】:

  • @jak:看看remove()的描述:它将所有不等于传递的值的值移动到范围[begin,end)的开头。使用您在问题中的示例,您将得到5,9,2,0,7,7。然而,remove() 将迭代器返回到新端,vec.erase() 可以根据需要删除过时的元素(即此处的第二个 7)。
  • @Assimilater:没必要。
  • @GeorgFritzsche 为什么你不能直接回答他的问题而不是给他发一个链接?是的,是 O(n)
  • @AlisherKassymov 因为在那里很容易找到答案。这是一种更好的学习方法。不同的人有不同的方法,值得尊重。
  • 这个算法的愚蠢之处在于,当它找到第一个匹配时,remove 并没有停止。继续比较列表的其余部分是低效的。因此,如果向量中可能存在相同值的多个副本,这很好,但对于唯一值向量的常见场景,这不是一个好的答案。在这种情况下,std::find 是更好的选择。
【解决方案2】:

Eric Niebler 正在研究范围提案,其中一些 examples 展示了如何删除某些元素。删除 8. 是否创建一个新向量。

#include <iostream>
#include <range/v3/all.hpp>

int main(int argc, char const *argv[])
{
    std::vector<int> vi{2,4,6,8,10};
    for (auto& i : vi) {
        std::cout << i << std::endl;
    }
    std::cout << "-----" << std::endl;
    std::vector<int> vim = vi | ranges::view::remove_if([](int i){return i == 8;});
    for (auto& i : vim) {
        std::cout << i << std::endl;
    }
    return 0;
}

输出

2
4
6
8
10
-----
2
4
6
10

【讨论】:

    【解决方案3】:

    您可以使用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);
    

    【讨论】:

    • 如果您只期望该值出现一次,这很好。
    • @TomášZato:或者只想删除一个,这个问题似乎就是这样。
    • 要删除所有值,初始化 position = myVector.begin() 并将所有内容包含在 while(position != myVector.end()) 循环中
    • Error C2676 binary '==': 'action' does not define this operator or a conversion to a type acceptable to the predefined operator in xutility。从字面上看,我在这个例子中遇到的任何方法都会给我这个错误。
    • 投了反对票,因为这真的不是你应该这样做的方式(最赞成的答案是正确的方式)。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 2020-05-10
      相关资源
      最近更新 更多