Python小酷库系列:bidict,可以双向查询的dict
bidict,可以双向查询的dict
- 基本使用
- 创建双向字典
- 正向查找(key → value)
- 反向查找(value → key)
- 添加新项
- 删除项
- 进阶功能
- 使用 ~ (.inverse)获取逆映射
- 使用 namedbidict 创建具名双向字典
- 批量更新
- 不可变双向映射
bidict 是一个高性能的双向字典库,所谓 双向字典,就是你可以通过键(key)查找值(value),也可以通过值反查键。我们知道,dict中键是唯一的,但值可以重复,而在 bidict 中,键和值都必须唯一,确保映射的双向性。
相比于使用组合使用dict,bidict主要有以下优点:
- 高效的查找操作:bidict 使用哈希表实现,确保键和值的查找操作都具有常数时间复杂度(O(1)),与原生字典相当。
- 内存优化:相比手动维护两个字典(一个正向,一个反向),bidict 通过内部机制共享数据结构,减少冗余存储,提高内存利用率。
- 冲突检测与强制更新:在插入新项时,bidict 会自动检测键或值的重复,防止数据不一致。对于需要覆盖的情况,提供了 forceput 方法,允许强制更新。
- 轻量级实现:bidict 仅依赖 Python 标准库,无需额外安装其他依赖,适合嵌入式或资源受限的环境。
下面我们通过一个例子来实践一下bidict的使用:
现有一组学生信息数据,对于一个学生来说,他的身份证号是唯一的,而学号也是唯一的,数据如下表,这时我们就可以使用“身份证号<->学号“构建一个bidict双向字典。
身份证号 | 学号 | 姓名 |
---|---|---|
SFZ1001001 | XH101111 | 小赵 |
SFZ2021011 | XH101112 | 小钱 |
SFZ3121212 | XH101113 | 小孙 |
SFZ2231221 | XH101114 | 小李 |
SFZ4231511 | XH101115 | 小王 |
基本使用
创建双向字典
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 namedbidictStudentInfo = 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 frozenbidictfb = frozenbidict({'a': 1, 'b': 2})
print(fb['a'])
print(fb.inverse[2])
# 如果进行新增/更新操作,则会报错
fb['c'] = 3