vector.erase() 和 remove_if() 有问题
having trouble with vector.erase() and remove_if()
在使用 remove_if 之前,我使用的是删除。假设我有 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 的上下文中工作。这是我的代码:
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 值,但不确定如何将 "if int a is in this vector return 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
只需使用 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
的谓词(或你的 class 的另一个成员函数),那么正如评论中提到的,你应该将它设为最好是静态成员函数。
您也可以 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()
foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());
如果您想删除所有偶数,那么我建议您使用 lambda 而不是使用 class 成员函数。
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
在使用 remove_if 之前,我使用的是删除。假设我有 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 的上下文中工作。这是我的代码:
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 值,但不确定如何将 "if int a is in this vector return 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
只需使用 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
的谓词(或你的 class 的另一个成员函数),那么正如评论中提到的,你应该将它设为最好是静态成员函数。
您也可以 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()
foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());
如果您想删除所有偶数,那么我建议您使用 lambda 而不是使用 class 成员函数。
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