std::set 比较器 - 基于多个属性的 STL 排序

问题描述 投票:0回答:3

我正在使用自定义比较器测试

std::set
。但我看到同一个对象被插入两次。

以下是对象类:

 class Info
    {
        public:
            Info(string n, string oN, int dom):
                    name(n),
                    objName(oN),
                    domain(dom)
            {}
    

        void setName(std::string n) { name = n;}
        void setObjName(std::string n) { objName = n;}
        void setDomain(int dom) { domain = dom; }

        std::string getName() const { return name;}
        std::string getObjName() const { return objName;}
        int getDomain() const { return domain;}

    private:
        std::string name;
        std::string objName;
        int domain;
};

以下是我的自定义比较器:

struct InfoCmp {
bool operator() (const Info &lhs, const Info &rhs) const {
    if((lhs.getName() < rhs.getName()) || (lhs.getObjName() < rhs.getObjName()) || (lhs.getDomain() < rhs.getDomain()) ){
        return true;
        }
    return false;
    }
};

使用方法如下:

Info rst1("rst1", "rstObj1", 1);
Info rst2("rst2", "rstObj2", 2);
Info rst3("rst1", "rstObj3", 3);

std::set<Info,InfoCmp> resetSet;

resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);
resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);

我看到

rst2
插入了两次,但根据我的比较器,它不应该是这样的。

c++ stl set comparator strict-weak-ordering
3个回答
1
投票

我看到您在从评论中认识到您的原始解决方案没有按照

set
的要求强加严格的对象排序后,已经提出了自己的解决方案。这是一个不同的版本,只需要
operator<
而不需要
operator==
,使其与标准库的类和算法保持一致。如果您是例如,它也会简化事情。进行不区分大小写的比较。

struct InfoCmp {
    bool operator() (const Info &lhs, const Info &rhs) const {
        if(lhs.getName() < rhs.getName())
            return true;
        if(rhs.getName() < lhs.getName())
            return false;
        if(lhs.getObjName() < rhs.getObjName())
            return true;
        if(rhs.getObjName() < lhs.getObjName())
            return false;
        return lhs.getDomain() < rhs.getDomain();
        }
    };

1
投票
struct InfoCmp2 {
    bool operator() (const Info &lhs, const Info &rhs) const {
        return std::make_tuple(lhs.getName(), lhs.getObjName(), lhs.getDomain()) < std::make_tuple(rhs.getName(), rhs.getObjName(), rhs.getDomain());
    }
};

这个运算符也可以用

make_tuple
编写,并且工作正常。


0
投票

按照 Cory Kramer 的建议,在比较器中添加严格的排序解决了问题。

struct InfoCmp {
    bool operator() (const Info &lhs, const Info &rhs) const {
        if((lhs.getName() < rhs.getName())
           || ( (lhs.getName() == rhs.getName()) && (lhs.getObjName() < rhs.getObjName()) )
           || ( (lhs.getName() == rhs.getName()) && (lhs.getObjName() == rhs.getObjName()) && (lhs.getDomain() < rhs.getDomain()) )){
            return true;
            }
        return false;
        }
    };
© www.soinside.com 2019 - 2024. All rights reserved.