【问题标题】:having trouble with vector.erase() and remove_if()vector.erase() 和 remove_if() 有问题
【发布时间】:2023-03-21 02:17:01
【问题描述】:

在使用 remove_if 之前,我使用的是 remove。所以说如果我有 vec = {1, 2, 2, 2, 5},并且想要删除所有 2,我会这样做:

for (vector<int>::iterator it = vec.begin(); it!= vector.end(); ++it){
    if (*it == 2){
       vec.erase(remove(vec.begin(),vec.end(), *it), vec.end());
    }
}

这将不起作用,因为在删除过程中遍历向量是不可能且不合逻辑的。

然后我发现了 remove_if()。但是,由于某种原因,我无法让它在类的上下文中工作。这是我的代码:

class SomeClass{
    private:
       vector<int> vec;
    public:
       SomeClass(){
           //initalizae vec to {1,2,2,2,4,5,6,8}
       }
       bool is_even(int value){
           return value % 2 == 0;
       }
       void delete(int a){
           vec.erase(remove_if(vec.begin(), vec.end(), a), vec.end());
       }
       void delete_even(int a){
           vec.erase(remove_if(vec.begin(), vec.end(), this->is_even(a)), vec.end());
       }

我猜测 void delete 将不起作用,因为 a 是一个 int 并且我需要一个 bool 值,但不确定如何将“如果 int a 在此向量中返回 true”表示为 remove_if 的第三个参数。我希望 void delete_even 可以工作,但我得到了

note: in instantiation of function template specialization 'std::__1::remove_if<std::__1::__wrap_iter<int *>, bool>' requested here

【问题讨论】:

  • void delete(int a) 疯了
  • 你为什么要抹掉remove_if的返回??
  • @YSC 因为这就是它与迭代器和remove 一起工作的方式。令人困惑,但确实如此。
  • @MicroVirus 没错,我的错。周末在这里;)

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


【解决方案1】:

只需使用std::remove 从集合中删除int 值,无需自己搜索:

vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());

这将从vec 中删除所有出现的2

remove_if 的用法是一样的,只是你给一个谓词(通常是一个函数)而不是一个元素;如果您可以使用 C++11,则可以将其与 lambda 一起使用:

vec.erase(std::remove_if(vec.begin(), vec.end(), [](int a) {return a % 2 == 0;}), vec.end());

如果您想使用is_even 作为remove_if(或您的类的另一个成员函数)的谓词,那么如 cmets 中所述,您最好将其设为静态成员函数。 你也可以bind 给非静态成员,但这里没有真正的理由这样做;但如果您好奇,请参阅Using std::bind with member function, use object pointer or not for this argument?,问题本身包含正确的语法。 is_even 的静态示例:

 static bool is_even(int value) {
     return value % 2 == 0;
 }

 void delete_even(int a){
     vec.erase(remove_if(vec.begin(), vec.end(), is_even), vec.end());
 }

【讨论】:

  • 你能解释一下谓​​词是什么,这与我发布的错误有关吗?并且 remove 也可以在 delete_even 方法中使用吗?
  • 谓词只是一个“函数”的花哨词,它可以根据其输入返回truefalse。例如,您的 is_even 是一个谓词。
  • 我认为问题在于您不能将成员函数用于谓词。除非是成员函数 operator()。
【解决方案2】:

如果您只想从向量中删除一些值,则可以使用remove()

foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());

如果您想删除所有偶数,那么我建议您使用 lambda,而不是使用类成员函数。

foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());

这是一个使用两种方法的示例

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> foo = {1,2,3,4,5,6,7,8,9};
    // remove all even numbers
    foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());
    for (auto e : foo)
        std::cout << e << std::endl;
    std::cout << std::endl;
    // remove all elemenets that match some_value
    foo = {1,2,2,2,2,2,7,8,9};
    int some_value = 2;
    foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());
    for (auto e : foo)
        std::cout << e << std::endl;
}

输出:

1
3
5
7
9

1
7
8
9

Live Example

【讨论】:

  • 自动是干什么用的?变量不默认为自动吗?
  • @jasonadams auto 是一个说明符,它告诉编译器推断变量的正确类型。 变量不默认为自动是什么意思?
  • 我不知道 auto 是用来做什么的,所以我去了这个链接:stackoverflow.com/questions/1046477/…
  • @jasonadams 啊。 C++11 及更高版本中的 Auto 是不同的。见:en.cppreference.com/w/cpp/language/auto
猜你喜欢
  • 2023-02-05
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 2011-02-25
  • 2021-03-08
  • 2012-12-04
相关资源
最近更新 更多