c++中以类对象作为key用于unordered_map、map,以及std::tie技巧使用

2023-05-16

我有一个类

class UserRegion {
public:
    int country_id;
    int province_id;
    int isp_id;
}

如果想让其作为std::unordered_map的key的话需要添加两个条件:

  • 1、operator==,用于查找
  • 2、实现对应的hash类
#include <iostream>
#include <unordered_map>
// 用于表示用户区域信息
class UserRegion {
public:
    int country_id;
    int province_id;
    int isp_id;

    bool operator==(const UserRegion& other) const {
        return country_id == other.country_id && province_id == other.province_id &&
               isp_id == other.isp_id;
    }
};

struct HashUserRegion {
    std::size_t operator()(const UserRegion& ur) const {
        std::size_t h1 = std::hash<int>{}(ur.country_id);
        std::size_t h2 = std::hash<int>{}(ur.province_id);
        std::size_t h3 = std::hash<int>{}(ur.isp_id);
        return h1 ^ (h2 << 1) ^ (h3 << 2);
    }
};

int main() {
    std::unordered_map<UserRegion, std::string, HashUserRegion> user_region_map = {
            {{1, 1, 1}, "user1"},
            {{1, 2, 1}, "user2"},
            {{2, 1, 2}, "user3"}
    };
    UserRegion test = {1, 1, 1};
    if (user_region_map.find(test) != user_region_map.end()) {
        std::cout << user_region_map[test] << std::endl;
    }
    // 遍历 unordered_map
    for (auto it = user_region_map.begin(); it != user_region_map.end(); ++it) {
        const UserRegion &ur = it->first;
        const std::string &user_name = it->second;
        std::cout << user_name << std::endl;
    }
    return 0;
}

如果想让其作为std::map的key的话需要添加一个条件:

  • 1、operator<,用于查找
    首先我们逻辑是按照成员顺序挨个比较,注意这里最里层的比较不能是<=,小于比较运算符返回 false 时,才认为相等。
bool operator<(const UserRegion& other) const {
    if (country_id < other.country_id) return true;
    else if (country_id == other.country_id) {
        if (province_id < other.province_id) return true;
        else if (province_id == other.province_id) {
            if (isp_id < other.isp_id) return true;
            else return false;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

当比较多个成员变量时,可以使用 std::tie 函数来简化比较操作。std::tie 函数可以将多个变量绑定在一起,形成一个元组,然后使用元组的比较操作符进行比较。这样可以避免手动编写多个比较操作符,从而简化代码。

使用 std::tie 函数重写 operator< 函数的示例代码如下:

bool operator<(const UserRegion& other) const {
    return std::tie(country_id, province_id, isp_id) <
           std::tie(other.country_id, other.province_id, other.isp_id);
}

在这个例子中,std::tie 函数将 country_id、province_id 和 isp_id 绑定在一起,形成一个元组。然后使用 < 运算符比较两个元组,从而实现了 UserRegion 结构体的比较操作。这种写法简洁明了,易于理解和维护。
需要注意的是结构体的成员变量应该是不可变的,以避免在哈希表or红黑树中修改键值对。如果在哈希表or红黑树中修改键值对,将会导致哈希表or红黑树的内部结构被破坏,从而导致未定义的行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++中以类对象作为key用于unordered_map、map,以及std::tie技巧使用 的相关文章

  • Visual C++ 2010 在调试时拒绝显示 std::string 值。显示<错误指针>

    我有一种奇怪的感觉 就像这是最近出现的问题 并且发生在两台不同的计算机上 当我调试并尝试查看 STL 中的 std string 的值时 它显示为值 它说它的大小是15 容量是一些乱码的巨大数字 数组值本身都显示 CXX0030 错误 无法
  • 为什么 c++ std::min 在 O0 上编译时不能使用静态字段作为其参数?

    同样的代码 用O0编译 会报错 Name test cpp Author Version Copyright Your copyright notice Description Hello World in C Ansi style inc
  • 如何使用 tie() 仅为某些包重定向 STDOUT、STDERR?

    我需要使用一些不幸记录诊断的库 发送至 STDOUT 和 STDERR 的消息 通过使用tie 我可以重定向那些 写入捕获这些的函数 既然我不想要全部 我的程序的 STDOUT 和 STDERR 输出通过 捆绑手柄 我只想对某些包裹执行此操
  • 根据插入时间从 std::map 中删除元素

    我需要根据插入时间 或其他比这更有效的方法 从 std map 中删除元素 该地图可能会包含数千个元素 如果我存储时间并迭代地图以检查每个元素的时间 那么最终可能会非常耗时 有谁知道如何在 std map 变老时删除它们 The std m
  • 在 std 命名空间中定义的好友类:有任何保证吗?

    我回答的时候就出现了这个问题这个问题 https stackoverflow com questions 15193108 c unique ptr versus friend class private destructor 151931
  • c++ max_element 每n个元素

    有没有办法比较每 N 个元素来找到容器中的最大元素并返回索引 使用 STL BOOST 或 其他库 对于每个 N 我的意思是使用 std max element 但将 for 的增加从 first 更改为 first n based on
  • Python 字典键中的空格

    我知道 Python 字典键中可以有空格 但这被认为是糟糕的编程吗 我在 PEP 中找不到任何与此相关的内容 编辑以澄清 在我正在做的一个项目中 我正在研究解析 Apache 的记分板输出的东西mod status 请参阅下面的示例输出 我
  • 是否可以处理 HTML 输入字段中的向上/向下键?

    我正在为输入文本字段构建自动完成功能 目前我可以使用鼠标单击来选择选项 我想添加键盘控制以允许自动完成控制 我监控了onkeyup事件中的键码 出现向上 向下键 键码都是0 我想知道是否有更好的方法可以做到这一点 Thanks 键码 37
  • 使用 data.table 中的多个键来获得条件搜索

    我有一个data table首先 我想根据某些条件获得一个子集 例如 我有 library data table dt lt data table rn 1 10 B rep 1 2 5 dt rn B 1 1 1 2 2 2 3 3 1
  • tcl 暂停并等待按键继续

    我正在 tcl 中寻找一种方法来暂停脚本 例如在使用 puts 进行一些输出之后 并等待用户按下按键 然后再继续输出剩余的文本 你只需使用gets从标准输入读取 proc pause message Hit Enter to continu
  • 将两个键与 std::map 一起使用的最佳方法是什么?

    我有一个std map我用来存储 x 和 y 坐标的值 我的数据非常稀疏 所以我不想使用数组或向量 这会导致内存的大量浪费 我的数据范围从 250000到250000 但我最多只有几千个点 目前我正在创建一个std string与两个坐标
  • 计算结构向量中的匹配项

    我有一个问题 要求我计算该数组中使用以下任一方法的实例的数量std count or std find 我知道如何使用标准数据 参见底部代码 类型来执行此操作 但不知道如何使用NameContainer我正在使用的 Type struct
  • Python - 查找字典中最长(最多单词)的键

    有没有一种方法可以快速查询字典对象以找到单词最多的键 所有键都是字符串类型 即 如果具有最大键的项目有五个单词 这是最大的键 3 我如何快速查询字典并返回 int 5 最好的 乔治娜 这将为您提供密钥 max d key lambda x
  • 在hbase中创建表

    我是 hbase 和 hadoop 的新手 无论如何 我已经成功建立了一个由3台机器组成的hadoop集群 现在我需要一些帮助来建立数据库 我有一个表 评论 包含字段 user id comments 对评论的评论 可以多个 和状态字段相同
  • Outlook 添加、文本框、删除\退格键不起作用

    我开发了一个 Outlook 插件 自定义任务窗格 在用户控件中带有 Web 浏览器 当我在网络浏览器的文本框中写入内容时 退格键或删除按钮旁边的所有功能都运行良好 但我无法使用这些键 我是否遗漏了什么 我迟到了几年 但我设法解决了这个问题
  • openssl-使用密钥和 IV 解密 Base64 字符串

    我正在尝试解密已在 openssl 中使用 aes256 加密的 base64 字符串 我获得了会话密钥和 IV 它们是用我的密钥加密的 我将它们转换为十六进制 以便可以使用以下 openssl 命令 openssl enc d aes25
  • 基于输入键的 Tabindex 通过获取表单元素在 Jquery 中不起作用

    我有一个表单 我可以通过它获取所有表单元素serializeArray 我想要focus 使用 Enter 键根据其 tabindex 值在表单元素上 只有当它有价值时 否则就专注于它本身 对 jQuery 来说不太新鲜 所以如果有任何错误
  • python随机字典键,并访问它[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 import random Cards Spade 2 3 4 5 6 7 8 9 10 Jack Queen King
  • Google App Engine 密钥中允许使用哪些字符?

    在测试我的 Google App Engine 应用程序时 我搜索包含应用程序引擎密钥的链接 例如 story ag5yZXBsaWUtdGVzdGluZ3IMCxIFU3RvcnkY w0M 这些键中允许使用哪些字符 我一直在使用正则表达
  • 为什么我收到 string does not name a type 错误?

    game cpp include

随机推荐