有自定义的数据类型Point,存放在std::vector中,想对其进行去重的操作。
Point.h:
struct Point
{
double X, Y, Z;
Point() {};
Point(double x,double y,double z)
:X(x),Y(y),Z(z){}
};
main.cpp:
#include1. std::sort#include #include "Point.h" #include using namespace std; int main() { vector v; Point p0(0, 0, 0); Point p1(1, 2, 3); Point p2(0, 0, 0); Point p3(0, 0, 0); Point p4(1, 0, 5); Point p5(1, 2, 3); v.push_back(p0); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); v.push_back(p5); return 0; }
将指定范围内的元素按升序方式进行排序。
有两种使用方式:
- Point实现操作符重载:<
- 使用lambda表达式
struct Point
{
double X, Y, Z;
Point() {};
Point(double x,double y,double z)
:X(x),Y(y),Z(z){}
// 依次比较x,y,z坐标
bool operator<(const Point& other) const
{
if (this->X < other.X)
return true;
else if (this->X == other.X)
{
if (this->Y < other.Y)
return true;
else if (this->Y == other.Y)
{
if (this->Z < other.Z)
return true;
}
}
return false;
}
};
// 调用已实现的<的操作符重载 ::sort(v.begin(), v.end());
最后排序的结构为:
// 使用lambda手动指定比较规则:根据Z值,按从大到小排列
::sort(v.begin(), v.end(), [](Point a, Point b)
{
if (a.Z>b.Z)
return true;
return false;
});
输出结果为:
对指定范围内的元素进行去重操作,实际逻辑是:用下一个不重复的元素替换重复元素。
就因为这一点,所以在使用std::unique的时候,需要先对元素进行排序。
我们先来试一下不排序的结果:
vectorx; x.push_back(0); x.push_back(0); x.push_back(1); x.push_back(1); x.push_back(0); x.push_back(0); x.push_back(5); ::unique(x.begin(),x.end());
运行结果为:
显然我们并没有得到正确的结果。进行排序:
vectorx; x.push_back(0); x.push_back(0); x.push_back(1); x.push_back(1); x.push_back(0); x.push_back(0); x.push_back(5); ::sort(x.begin(), x.end()); ::unique(x.begin(),x.end());
结果为:
unique函数的返回值为iterator,即从begin到it之间的元素就是没有重复的元素,而it之后的元素都是无效值。
vector2.1 方式1:操作符重载==::iterator it = ::unique(x.begin(),x.end());
struct Point
{
double X, Y, Z;
Point() {};
Point(double x,double y,double z)
:X(x),Y(y),Z(z){}
bool operator==(const Point& other) const
{
return this->X == other.X && this->Y == other.Y && this->Z == other.Z;
}
bool operator<(const Point& other) const
{
if (this->operator==(other))
return false;
if (this->X < other.X)
return true;
else if (this->X == other.X)
{
if (this->Y < other.Y)
return true;
else if (this->Y == other.Y)
{
if (this->Z < other.Z)
return true;
}
}
return false;
}
};
调用:
vectorv; Point p0(0, 0, 0); Point p1(1, 2, 3); Point p2(0, 0, 0); Point p3(0, 0, 0); Point p4(1, 0, 5); Point p5(1, 2, 3); v.push_back(p0); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); v.push_back(p5); ::sort(v.begin(), v.end()); auto it = ::unique(v.begin(), v.end()); v.erase(it, v.end());
结果为:
::sort(v.begin(), v.end());
// 使用lambda自定义比较规则:若x坐标相等,则两个Point相等
auto it = ::unique(v.begin(), v.end(), [](Point a, Point b)
{
return a.X == b.X;
});
v.erase(it, v.end());
运行结果为:
在使用完unique之后,我们可以得到一个分界线iterator,有两种方式进行处理:
//v.erase(it, v.end());删除从it往后的所有元素 //v.resize((int)(::distance(v.begin(), it)));//保留从begin到it的所有元素3. 去重总结
- 用sort对集合中的元素进行排序:重载<或者lambda;
- 用unique对集合中的元素进行去重:重载==或者使用lambda;
- 用erase删除重复值或resize保留有效值。



