让我说一堂课
class sampleVector
{
public:
int a;
int b;
string c;
}
现在我有一个带有多个sampleVector对象的向量,但是该向量具有2(多个)连续个sampleVector对象,它们具有相同的a(例如5)值和b(例如10)。
现在我要从向量中删除所有具有a = 5和b = 10的sampleVector对象。
问题是,对于多个连续出现的情况,以下是一种解决方法:
for (;it!=itEnd;it++)
{
if (it->getA() == 5 && it->getB() == 10)
{
vec.erase(it);
it=vec.begin(); // Resetting this is must
}
}
但是我想知道如何为此使用“删除”,因为下面的方法不起作用:
for (;it!=itEnd;it++)
{
if (it->getA() == 5 && it->getB() == 10)
{
vec2.erase(remove(vec2.begin(), vec2.end(), *it), vec2.end()); // doesn't even compile
}
}
当我们具有原始数据类型的向量并且我们需要删除特定的值时,可以使用这种删除方式。但是对于非原始数据类型的向量,如何通过传递迭代器而不是值来使用“删除”?
答案 0 :(得分:6)
std::remove
documentation状态中,您无需为此使用循环;
从[first,last)范围中删除所有满足特定条件的元素
当您要删除仅与班级部分匹配的特定项目时,应使用std::remove_if
并提供谓词:
template <类ForwardIt,类UnaryPredicate> ForwardIt remove_if(ForwardIt first,ForwardIt last,UnaryPredicate p);
例如:
std::remove_if(std::begin(vec), std::end(vec),
[](sampleVector& v) { return (v.a == 5 && v.b==10); });
然后您可以像以前一样将其传递到std::erase
中。
答案 1 :(得分:2)
您可以通过两种方式实现这一点:向您的类添加一个比较运算符,或将std::remove_if
与进行比较的函数一起使用。
在大多数情况下,如果您有权访问类sampleVector
,则首选此方法。这样,您就可以将运算符与您的类一起分发,因此其他用户将不必为此编写函数。由于元素是公共的,因此您也可以将运算符作为非成员函数,但非成员函数将无法访问私有字段。
class sampleVector
{
public:
int a;
int b;
string c;
bool operator==(const sampleVector& other);
}
bool sampleVector::operator==(const sampleVector& other)
{
return a == other.a && b == other.b;
}
//somewhere else
sampleVector elementToRemove {5, 10, ""}; //or however you find the element you want to remove
std::erase(std::remove(vec2.begin(), vec2.end(), elementToRemove), vec2.end());
std::remove_if
如果您无法修改sampleVector
的内容,或者存在多种比较类的可能性(例如,此处仅检查a
和b
,则此方法更好)但在其他情况下,您也想比较c
。如果您想比较私人成员(除非您为他们提供吸气剂),那么它将不起作用。
std::erase(std::remove_if(vec2.begin(), vec2.end(), [](const sampleVector& v) {
return v.a == 5 && v.b == 10;}), vec2.end());
答案 2 :(得分:2)
实际上std :: remove算法不会删除矢量元素,但会在最后移动这些元素。 您可以使用下一种方法:
auto it = std::remove_if(vec.begin(), vec.end(), [](auto&& item)
{ return (item.a == 5 && item.b == 10); });
vec.erase(it, vec.end());
备注: std :: remove_if的1st和2nd参数是分别指示向量的开始和结束的迭代器。 第3个参数-是可调用对象(在我们的示例中是lambda),返回true-如果当前对象需要删除,则返回false。 此算法的返回值-在第一个移除对象上是迭代器。
答案 3 :(得分:1)
带有std::remove_if和vector.erase的示例
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
struct SampleVector
{
int a;
int b;
std::string c;
};
std::ostream& operator<<(std::ostream& to, const SampleVector & v)
{
return to << "{ a=" << v.a << ", b=" << v.b << ", c=" << v.c << " }";
}
int main(int argc, char const *argv[]) {
std::vector< SampleVector > data = { {5,10,"5-10"}, {3,12,"3-12"}, {5,10,"5-10"} };
std::cout << "Before [";
std::for_each(data.begin(), data.end(), [] (const SampleVector& v) {
std::cout << ' ' << v << ' ';
} );
std::cout << ']' << std::endl;
data.erase( std::remove_if(data.begin(), data.end(), [] (const SampleVector& v)
{ return 5 == v.a && 10 == v.b; } ), data.end() );
std::cout << "After [";
std::for_each(data.begin(), data.end(), [] (const SampleVector& v) {
std::cout << ' ' << v << ' ';
} );
std::cout << ']' << std::endl;
return 0;
}