Python小酷库系列:bidict,可以双向查询的dict


bidict 是一个高性能的双向字典库,所谓 双向字典,就是你可以通过键(key)查找值(value),也可以通过值反查键。我们知道,dict中键是唯一的,但值可以重复,而在 bidict 中,键和值都必须唯一,确保映射的双向性。

相比于使用组合使用dict,bidict主要有以下优点:

  1. 高效的查找操作:bidict 使用哈希表实现,确保键和值的查找操作都具有常数时间复杂度(O(1)),与原生字典相当。
  2. 内存优化:相比手动维护两个字典(一个正向,一个反向),bidict 通过内部机制共享数据结构,减少冗余存储,提高内存利用率。
  3. 冲突检测与强制更新:在插入新项时,bidict 会自动检测键或值的重复,防止数据不一致。对于需要覆盖的情况,提供了 forceput 方法,允许强制更新。
  4. 轻量级实现:bidict 仅依赖 Python 标准库,无需额外安装其他依赖,适合嵌入式或资源受限的环境。

下面我们通过一个例子来实践一下bidict的使用:

现有一组学生信息数据,对于一个学生来说,他的身份证号是唯一的,而学号也是唯一的,数据如下表,这时我们就可以使用“身份证号<->学号“构建一个bidict双向字典。

身份证号学号姓名
SFZ1001001XH101111小赵
SFZ2021011XH101112小钱
SFZ3121212XH101113小孙
SFZ2231221XH101114小李
SFZ4231511XH101115小王

基本使用

创建双向字典

from bidict import bidict
student_info = bidict({
	'XH101111': 'SFZ1001001', 
	'XH101112': 'SFZ2021011'
	'XH101113': 'SFZ3121212', 
	'XH101114': 'SFZ2231221', 
	'XH101115': 'SFZ4231511'
})

正向查找(key → value)

print(student_info['XH101111'])

反向查找(value → key)

print(student_info.inverse['SFZ1001001'])

添加新项

student_info['XH101116'] = 'SFZ8223521'

删除项

del student_info['XH101116'])

进阶功能

使用 ~ (.inverse)获取逆映射

student_info_inv = ~student_info
# 等同于 student_info_inv = student_info.inverse
print(student_info_inv['SFZ1001001']) 
# 等同于
print(student_info.inverse['SFZ1001001'])

注意:
1、使用 ~ 运算符时,需加括号以确保优先级正确,如 (~student_info)[3]
2、逆映射对象是一个轻量级视图对象,和原字典共享数据。

使用 namedbidict 创建具名双向字典

from bidict import namedbidict

StudentInfo = namedbidict('StudentInfo', 'id_number', 'student_number')
student_info = StudentInfo({
	'XH101111': 'SFZ1001001', 
	'XH101112': 'SFZ2021011'
	'XH101113': 'SFZ3121212', 
	'XH101114': 'SFZ2231221', 
	'XH101115': 'SFZ4231511'
})

print(student_info.id_number['SFZ1001001'])
print(student_info.student_number['XH101111'])

批量更新

student_info.update({'XH101116': 'SFZ8223521', 'XH101117': 'SFZ6352329'})

如果需要强制更新(即覆盖已有的键或值),可以使用 forceupdate 方法:

student_info.forceupdate({'XH101111': 'SFZ1001002'})

不可变双向映射

类似于 frozenset,可用于哈希键、函数缓存等场景:

from bidict import frozenbidict

fb = frozenbidict({'a': 1, 'b': 2})
print(fb['a'])        
print(fb.inverse[2])  
# 如果进行新增/更新操作,则会报错
fb['c'] = 3  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值