从C++中的非基元对象的向量中移除所有匹配元素
Remove all matching elements from vector of non-primitive objects in C++
假设我有一个类:
class sampleVector
{
public:
int a;
int b;
string c;
}
现在我有一个带有sampleVector的多个对象的向量,但该向量有两个(多个(连续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
}
}
当我们有一个原始数据类型的向量,并且有一个需要删除的特定值时,我们可以使用这种删除方式。但对于非原始数据类型的向量,我们如何通过传递迭代器而不是值来使用"remove"?
您不需要使用循环作为std::remove
文档状态;
从范围[第一个,最后一个(中删除所有满足特定标准的元素
如果要删除只与类的一部分匹配的特定项,则应使用std::remove_if
并提供谓词:
模板<class ForwardIt,class UnaryPredicate>ForwardIt remove_if(ForwardIt first,ForwardIt last,UnaryPredictate p(;
例如:
std::remove_if(std::begin(vec), std::end(vec),
[](sampleVector& v) { return (v.a == 5 && v.b==10); });
然后,您可以像以前一样将其传递到std::erase
中。
您可以通过两种方式实现这一点:向类中添加一个比较运算符,或者将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
(,则这种方法会更好。如果你想比较私人成员,这是行不通的(除非你为他们提供getter(。
std::erase(std::remove_if(vec2.begin(), vec2.end(), [](const sampleVector& v) {
return v.a == 5 && v.b == 10;}), vec2.end());
实际上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的第1个和第2个参数是迭代器,分别指示向量的开始和结束。第三个参数-是可调用的对象(在我们的例子中是lambda(,如果当前对象需要删除,则返回true,否则返回false。此算法的返回值-是第一个删除对象时的迭代器。
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;
}
- 复制包含C++所有元素的对象!(构造函数和赋值,最佳实践?
- 为什么平均打印数组元素比打印单个对象慢C++?
- push_back通过自行创建的对象获取最后一个元素的向量
- 从自定义类获取对象向量中的 max 元素
- 选择一个元素而不是一个对象的数组的原因
- 数组对象的生存期是否在重用其元素存储时结束?
- 如何替换双端对象中的元素?
- 打印出对象向量中的每个元素C++
- C++ - 打印派生类对象的矢量<base*> 元素
- 从C++中的非基元对象的向量中移除所有匹配元素
- 如何将某个元素从shared_ptr擦除到对象向量?
- 从对象数组中删除元素
- 访问指向对象指针向量的指针的第一个元素?
- 在指向对象的指针的动态数组上插入新元素
- 打印/修改类对象的特定成员变量,其类定义列表 (STL) 包含的元素类型
- 如何通过引用对用户定义对象的类型集 (STL) 的数组元素进行增强迭代?
- 如何从对象指针的向量中正确清理元素
- ptrdiff_t可以表示指向同一数组对象元素的指针的所有减法吗?
- 如何遍历 QStack 对象的元素
- 在父类的构造函数中调用元素对象的构造函数