Python实现多键字典
实现背景
在许多场景中,有时需要通过多种信息来获取某个特定的值,而各种编程语言(包括Python)使用的字典(Dict)数据结构通常只支持单个键值寻值key-val对,即“一对一”(一个键对应一个值)。而“多对一”的字典在复杂信息映射下有很高实用价值。例如:
在实现非确定性下推自动机的时候,转移函数出现下面的形式:
δ(q,X)={(p,Z)}。\delta(q,X) = \{(p,Z)\}。 δ(q,X)={(p,Z)}。
如果采用“一对一”字典的形式,那么只能以qqq作为键(key),(X,p,Z)(X,p,Z)(X,p,Z)的集合作为其对应的值(val)。即dict[q] = {(X,p,Z)}。这样在访问和设置值的时候,遍历的复杂度显然增加了。
显然我们更希望采用形如d[q][X]={(p,Z)}的形式,以q,X作为一对键值去访问和获取(p,Z)对。这就希望有一种数据结构能够实现“多对一”的访问。
为此,可以设计“多键字典”来满足该要求。即对于一个键的个数为nnn的多键字典DDD,它可以通过:
D[key1][key2]...[keyn]D[key_1][key_2]...[key_n] D[key1][key2]...[keyn]
的方式,来获取键值对(key1,key2,...,keyn)(key_1,key_2,...,key_n)(key1,key2,...,keyn)所对应的值。
设计思路
有两种方式可以实现上面提到的“多键字典”。
- 第一种方式是将给定的多键对(multi-keys-pair)转化为一个字符串进行映射:
对于给定键值对(key1,key2,...,keyn)(key_1,key_2,...,key_n)(key1,key2,...,keyn),可以将其转化为一个字符串:key_1,key_2,...key_n(即所有键之间用逗号分隔),然后用已有的字典dict映射即可。注意,键之间一定要有分隔符,如果直接连接起来的话,有可能会造成哈希冲突导致两个不同的多键对被映射到同一处。例如:(aa,b)和(a,ab)中的键如果直接连接都会形成aab的字符串,导致哈希冲突。这种方式实现起来比较简单。 - 第二种方式也是本文所介绍和实现的方式:
采取”嵌套字典”的作法,这种方法也很容易想到,具体做法如下:- 设置“根字典”。
- 对于给定的多键对(key1,key2,...,keyn)(key_1,key_2,...,key_n)(key1,key2,...,keyn)和其对应的值valvalval,进行映射时按照下面的规则:
- 令d=root_dictd = root\_dictd=root_dict
- 遍历多键对key1,key2,key3,...,keyn−1key_1,key_2,key_3,...,key_{n-1}key1,key2,key3,...,keyn−1:
- 如果keyi(i≤n−1)key_i(i\leq n-1)keyi(i≤n−1)不在ddd中,那么令d[keyi]=new_dictd[key_i]=new\_dictd[keyi]=new_dict(否则不需要进行这一步)。然后令d=d[keyi]d=d[key_i]d=d[keyi](进行字典的嵌套)
- 令d[keyn]=vald[key_n]=vald[keyn]=val。进行完上一步的的时候,ddd已经指向了“最后一层”字典,这时才真正地对
multi_keys~val进行映射。
字典的嵌套如下图所示:

此外为了方便,需要设置一个集合对多键对进行存储以便之后获取(对应dict.keys())。
代码实现
除了上面介绍的基本原理,还实现了字典的诸如keys(),values(),items()的常用操作,以及对in进行重载等:
import copy
from typing import List,Set,Tuple,Any
class multi_key_dict:def __init__(self,key_num = 1) -> None:"""Initialize a multi-key dictionary.Args:key_num (int, optional):the number of keys. Defaults to 1."""assert key_num >= 1self.__key_num = key_numself.__dict = dict()self.__keys = set()passdef set_value(self,keys:tuple,val)->None:"""Set the value of multi_keys_dict[key_1][key_2]...[key_n].Args:keys (tuple): A tuple that contains keys in order. Its length must be equal to the number of keys.val (_type_): Value."""assert len(keys) == self.__key_numd = self.__dictfor i in range(0,self.__key_num-1):key = keys[i]if key not in d:d[key] = dict()d = d[key]d[keys[self.__key_num -1]] = valself.__keys.add(keys) def get_value(self,keys:tuple)->Any:"""Get the value of multi_keys_dict[key_1][key_2]...[key_n].Args:keys (tuple): A tuple that contains keys in order. Its length must be equal to the number of keys."""assert len(keys) == self.__key_numd = self.__dictfor i in range(0,self.__key_num):d = d[keys[i]]return ddef keys(self)->Set[tuple]:"""Get all keys of the multi_key_dict."""return self.__keys.copy()def values(self)->List[Any]:"""Get all values of the multi_key_dict."""values = []for key in self.__keys:values.append(self.get_value(key))return valuesdef items(self)->Set[Tuple[Tuple,Any]]:"""Get set of all "(keys,val)" in multi_keys_dict."""mutli_keys_dict_items = set()for keys in self.__keys:val = self.get_value(keys)mutli_keys_dict_items.add((keys,val))return mutli_keys_dict_itemsdef __contains__(self,keys:tuple)->bool:"""Check whether the given multi_keys is in the dict.Args:keys (tuple): A tuple that contains keys in order. Its length must be equal to the number of keys.Returns:bool: The result."""assert len(keys) == self.__key_numif keys in self.__keys:return Truereturn Falsedef clear(self)->None:"""Clear all the "keys-val" pairs in the dict.Note that the number of keys is not reset."""self.__dict.clear()self.__keys.clear()def keys_num(self)->int:"""Get the number of keys.""" return self.__key_numdef __str__(self) -> str:items = self.items()s = str()for key,val in items:s += f'{key} : {val}\n'return sdef copy(self):"""Return a deep copy of this dict."""copy.deepcopy(self)
进行测试:
def test_multi_keys_dict():d = multi_key_dict(3)l = [('a','b','c'),('d','e','f'),('g','h','i'),('g','h','j')]# test 'set_value' and 'get_value'for i in range(0,len(l)):d.set_value(l[i],i)assert d.get_value(l[i]) == i# test 'keys'keys = d.keys()for elem in l:assert elem in keys# test 'values':values = d.values()for i in range(0,len(l)):assert i in values# test 'items':items = d.items()for i in range(0,len(l)):assert (l[i],i) in items# test 'in':for elem in l:assert elem in d# test 'clear':d.clear()assert len(d.keys()) == 0print('Test passed!')if __name__ == '__main__':test_multi_keys_dict()
相关文章:
Python实现多键字典
实现背景 在许多场景中,有时需要通过多种信息来获取某个特定的值,而各种编程语言(包括Python)使用的字典(Dict)数据结构通常只支持单个键值寻值key-val对,即“一对一”(一个键对应一…...
【python socket】实现websocket服务端
一、获取握手信息首先通过如下代码,我们使用socket来获取客户端的握手信息import socketsock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(("127.0.0.1", 8002)) sock.li…...
PANGO的CFG那些事
先来看位于VCCIOCFG这个bank上引脚, MODE JTAG时,MODExxx. except 3’b000. 禁止设置为3’b000. Slave Parallel时,MODE 3’b110,不常用。 Slave Serial时,MODE 3’b111,不常用。 Master SPI 时&…...
路由协议(OSPF、ISIS、BGP)实验配置
目录 OSPF基础实验 建立OSPF邻居 配置虚连接 配置接口的网络类型 配置特殊区域 配置路由选路 配置路由过滤 ISIS基础实验配置 配置ISIS邻居建立 配置认证 配置路由扩散 配置路由过滤 配置定时器 BGP基础实验配置 建立BGP对等体 建立IBGP对等体 建立EBGP对等体…...
Python可变对象与不可变对象的浅拷贝与深拷贝
前言 本文主要介绍了python中容易面临的考试点和犯错点,即浅拷贝与深拷贝 首先,针对Python中的可变对象来说,例如列表,我们可以通过以下方式进行浅拷贝和深拷贝操作: import copya [1, 2, 3, 4, [a, b]]b a …...
滑模控制(Sliding mode control)快速入门
0. 简介 最近作者受到邀请,让我帮忙给刚入门的学弟讲讲滑模控制。可是作者也不知道怎么向未入门的学弟讲解这些基础知识,所以作者翻了翻近几年写的很好的文章以及视频。综合起来,来总结出一套比较基础,且适用于初学者的文章吧。这…...
golang的垃圾回收详解
golang的垃圾回收详解 一、三色标记法 作为一门现代化的语言,golang与java一样,都在语言中内置了垃圾回收的功能,不需要程序员自己去回收堆内存。而垃圾回收中,最重要的两个部分就是垃圾检测算法以及垃圾回收算法。垃圾检测算法决…...
线上负载过高排查(top/vmstat/ifstat/free/df)
目录 一、五大命令 二、故障排查步骤 1、top命令找出CPU占比最高的 2、ps -ef 或者 jps -l进一步定位 3、ps -mp位到具体线程或者代码 4、jstack精准定位到错误的地方 本文通过学习:周阳老师-尚硅谷Java大厂面试题第二季 总结的LinuxJDK命令操作相关的笔记 一…...
Java的注解(Annotation)
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。Java 中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。例如JUnit单元测试中的Test方法,可以使得方法直接运行。JUnit单元测试Test单元测试是针…...
信息系统项目管理师:配置管理
配置管理指的是在一个系统或软件中对配置项的管理,包括对配置项的定义、存储、跟踪和修改等一系列活动。配置项可以是硬件设备、软件组件、系统设置、网络配置等,配置管理旨在确保在不同时间点或环境下系统或软件的配置项的正确性和一致性。通过配置管理…...
web餐饮开源程序
简介 一款专门针对餐饮行业而开发桌面应用程序 技术 借助Panuon.UI.Silver控件库,开发的一款餐饮软件。 运行环境:.NETFramework,Versionv4.8。 运行数据库:MySql。 ORM框架:SqlSugar。 第三方插件:Panuon.UI.Silv…...
28个案例问题分析---027---单表的11个Update接口--MyBatis
一:背景介绍 项目开发中。我们使用的是MyBatis,在MyBatis的xml文件里,两个表的更新功能,写了足足11个更新接口,毫无复用的思想 这种方式可以正常的实现功能,但是没有复用,无论是从时间上还是维…...
大数据开发治理平台 DataWorks
序言学习下阿里DataWorks的设计理念以及要做的事情cuiyaonan2000163.com参考文档:https://www.aliyun.com/product/bigdata/idehttps://help.aliyun.com/document_detail/73015.htmlhttps://help.aliyun.com/document_detail/324149.html ----数据治理LaunchDataWorks基于阿里云…...
Xshell的下载、使用、配置【ssh、telnet、串口】
目录 一、概述 二、Xshell的使用 2.1 Xshell使用ssh协议远程连接Linux主机或服务器 2.2 Xshell使用telnet协议远程连接Linux开发板 2.3 Xshell使用SERIAL协议远程连接Linux开发板 三、Xshell常用配置 3.1 配置默认会话属性 一、概述 Xshell是由NetSarang公司开发的强大…...
C++回顾(七)—— 面向对象模型
7.1 静态成员变量和静态成员函数 7.1.1 静态成员变量 关键字 static 可以用于说明一个类的成员;静态成员提供了一个同类对象的共享机制;把一个类的成员说明为 static 时,这个类无论有多少个对象被创建,这些对象共享这个 static …...
开源监控服务uptime-kuma
好久没写文章了,刚好最近用了一个开源的监控服务,感觉蛮有意思的,记录一下 (一)安装 uptime-kuma安装方式有几种,这里当然是选择大家都爱的docker,一条命令搞定 docker run -d --restartalways -p 3001:…...
JavaScript混淆技术:了解其核心原理和常用手段
当今互联网时代,JavaScript已经成为了web前端开发的重点技术之一。其中,JavaScript代码的安全性问题一直是关注的焦点。为了保护JavaScript代码的安全性,很多人对其进行加密处理,众所周知,对于单纯的加密算法ÿ…...
大型医院云HIS系统:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发 融合B/S版电子病历系统
一套医院云his系统源码 采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发。融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。 文末卡片获取联系! 基于云计…...
SAP UI5 Upload/Download file through NetWeaver Gateway
1、创建 SEGW对象 2、创建Entity Type 要把Media 标识打上 3、 激活对象然后到DPC Class的扩展对象里面重定义 /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_STREAM /IWBEP/IF_MGW_APPL_SRV_RUNTIME~UPDATE_STREAM METHOD /iwbep/if_m…...
opencv校正图像
目录1、前言2、例程2.1、代码2.2、效果口罩说明书网页3、按步骤分析转灰度图降噪 Canny边缘检测膨胀(可视具体情况省略)轮廓检索选取角度1、前言 我们用相机拍照时,会因为角度问题造成拍歪,会影响图像的识别,这时就需…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
自定义线程池1.2
自定义线程池 1.2 1. 简介 上次我们实现了 1.1 版本,将线程池中的线程数量交给使用者决定,并且将线程的创建延迟到任务提交的时候,在本文中我们将对这个版本进行如下的优化: 在新建线程时交给线程一个任务。让线程在某种情况下…...
