栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 用sort和unique实现数据的去重

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 用sort和unique实现数据的去重

1. 应用场景

有自定义的数据类型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 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;
}
1. std::sort

将指定范围内的元素按升序方式进行排序。
有两种使用方式:

  • Point实现操作符重载:<
  • 使用lambda表达式
1.1 方式1:操作符重载<
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());

最后排序的结构为:

1.2 方式2:使用lambda
// 使用lambda手动指定比较规则:根据Z值,按从大到小排列
::sort(v.begin(), v.end(), [](Point a, Point b)
        {
            if (a.Z>b.Z)
                return true;
            return false;
        });

输出结果为:

2. std::unique

对指定范围内的元素进行去重操作,实际逻辑是:用下一个不重复的元素替换重复元素。
就因为这一点,所以在使用std::unique的时候,需要先对元素进行排序。
我们先来试一下不排序的结果:

vector 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 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::iterator it = ::unique(x.begin(),x.end());
2.1 方式1:操作符重载==
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 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());

结果为:

2.2 方式1:使用lambda
	::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());

运行结果为:

2.3 erase和resize

在使用完unique之后,我们可以得到一个分界线iterator,有两种方式进行处理:

//v.erase(it, v.end());删除从it往后的所有元素
//v.resize((int)(::distance(v.begin(), it)));//保留从begin到it的所有元素
3. 去重总结
  1. 用sort对集合中的元素进行排序:重载<或者lambda;
  2. 用unique对集合中的元素进行去重:重载==或者使用lambda;
  3. 用erase删除重复值或resize保留有效值。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1025562.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号