您好,欢迎来到世旅网。
搜索
您的当前位置:首页元素为自定义复合结构时 map,set 如何处理重复 key 及排序?

元素为自定义复合结构时 map,set 如何处理重复 key 及排序?

来源:世旅网

map, set 为 类模板,创建对象时需要指定 comparator, 如果不指定,默认使用 less. 因此,我们有 2 中方式可以选择:

1. 采用默认的 less, 我们需要重载关系运算符 "<". 但是我们不推荐这样做,这种方式可读性很差,因为我们从代码上根本看不出来 "<" 在哪里被调用;

2. 指定 functor, 传入的是一个functor 类名,而不是一个函数或 functor 对象。


下面的例子是一个排行榜,排序规则如下:

1. 按分数由高到低排;

2. 分数一样的情况下,按时间由新到旧排;

3. 时间也一样的情况下,按用户 ID 由小到大排。


方法一:重载 "<"

#include <iostream>
#include <map>


namespace test
{
    // sorted by score in descending order  >
    // then sorted by timestamp in descending order >
    // then sorted by id in ascending order
    class UserRank
    {
    public:
        UserRank(int id, int score, int timestamp) : id(id), score(score), timestamp(timestamp) { }
        ~UserRank() { }

        // The default comparator of map(set) is class template "less",
        // for user defined types, you must overload operator "<".
        friend bool operator<(const UserRank& left, const UserRank& right);
        friend void PrintUserRank(const UserRank& userRank);

    private:
        int id;
        int score;
        int timestamp;
    };

    bool operator<(const UserRank& left, const UserRank& right)
    {
        if (left.score == right.score)
        {
            if (left.timestamp == right.timestamp)
            {
                return (left.id < right.id);
            }
            else
            {
                return (left.timestamp > right.timestamp);
            }
        }
        else
        {
            return (left.score > right.score);
        }
    }

    void PrintUserRank(const UserRank& userRank)
    {
        std::cout << "id: " << userRank.id << ", "
            << "score: " << userRank.score << ", "
            << "timestamp: " << userRank.timestamp << std::endl;
    }
}


int main()
{
    ///
    std::map<test::UserRank, int> rankList;

    test::UserRank user1(1, 100, 2015);
    test::UserRank user2(1, 100, 2015);
    test::UserRank user3(1, 100, 2014);
    
    rankList[user1] = 1;
    rankList[user2] = 2;
    rankList[user3] = 3;

    std::cout << rankList[user1] << std::endl;   // 2
    std::cout << rankList[user2] << std::endl;   // 2
    std::cout << rankList[user3] << std::endl;   // 3

    ///
    // check order
    test::UserRank user4(1, 100, 2015);
    test::UserRank user5(1, 200, 2015);
    test::UserRank user6(1, 200, 2014);
    test::UserRank user7(2, 200, 2014);

    rankList.clear();
    rankList[user4] = 1;
    rankList[user5] = 2;
    rankList[user6] = 3;
    rankList[user7] = 4;

    for (std::map<test::UserRank, int>::iterator it = rankList.begin();
        it != rankList.end(); ++it)
    {
        PrintUserRank(it->first);
    }

    return 0;
}


方法二:自定义 functor

#include <iostream>
#include <map>


namespace test
{
    // sorted by score in descending order  >
    // then sorted by timestamp in descending order >
    // then sorted by id in ascending order
    class UserRank
    {
    public:
        UserRank(int id, int score, int timestamp) : id(id), score(score), timestamp(timestamp) { }
        ~UserRank() { }

        // The default comparator of map(set) is class template "less",
        // for user defined types, you must overload operator "<".
        friend struct UserComp;
        friend void PrintUserRank(const UserRank& userRank);

    private:
        int id;
        int score;
        int timestamp;
    };

    struct UserComp
    {
            bool operator()(const UserRank& left, const UserRank& right)
            {
                if (left.score == right.score)
                {
                    if (left.timestamp == right.timestamp)
                    {
                        return (left.id < right.id);
                    }
                    else
                    {
                        return (left.timestamp > right.timestamp);
                    }
                }
                else
                {
                    return (left.score > right.score);
                }
            }
    };

    void PrintUserRank(const UserRank& userRank)
    {
        std::cout << "id: " << userRank.id << ", "
            << "score: " << userRank.score << ", "
            << "timestamp: " << userRank.timestamp << std::endl;
    }
}


int main()
{
    ///
    std::map<test::UserRank, int, test::UserComp> rankList;

    test::UserRank user1(1, 100, 2015);
    test::UserRank user2(1, 100, 2015);
    test::UserRank user3(1, 100, 2014);

    rankList[user1] = 1;
    rankList[user2] = 2;
    rankList[user3] = 3;

    std::cout << rankList[user1] << std::endl;   // 2
    std::cout << rankList[user2] << std::endl;   // 2
    std::cout << rankList[user3] << std::endl;   // 3

    ///
    // check order
    test::UserRank user4(1, 100, 2015);
    test::UserRank user5(1, 200, 2015);
    test::UserRank user6(1, 200, 2014);
    test::UserRank user7(2, 200, 2014);

    rankList.clear();
    rankList[user4] = 1;
    rankList[user5] = 2;
    rankList[user6] = 3;
    rankList[user7] = 4;

    for (std::map<test::UserRank, int>::iterator it = rankList.begin();
        it != rankList.end(); ++it)
    {
        PrintUserRank(it->first);
    }

    return 0;
}




延伸阅读:






因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- esig.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务