有自定义的数据类型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
:
#include
#include
#include "Point.h"
#include
using namespace std;
int main()
{
vector<Point> 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;
}
将指定范围内的元素按升序方式进行排序。
有两种使用方式:
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
的时候,需要先对元素进行排序。
我们先来试一下不排序的结果:
vector<int> x;
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());
运行结果为:
显然我们并没有得到正确的结果。进行排序:
vector<int> x;
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之后的元素都是无效值。
vector<int>::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;
}
};
调用:
vector<Point> 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);
::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的所有元素
sort
对集合中的元素进行排序:重载<或者lambda;unique
对集合中的元素进行去重:重载==或者使用lambda;erase
删除重复值或resize
保留有效值。