Python多键同值字典如何压缩体积且保持单键正常访问?
解答
Python 原生标准库及 collections 模块未提供直接满足该需求的现成数据类型,你可以通过继承 dict 实现自定义类,完全兼容普通字典的访问逻辑,同时支持同值批量更新、导出压缩结构的能力。
实现代码
class GroupedValueDict(dict): def __init__(self, data=None): super().__init__() self._key_map = {} # 单键到值的映射,保证O(1)访问效率 self._value_groups = {} # 值到对应键集合的映射,用于批量更新 if data: # 初始化时自动对同值键分组 for k, v in data.items(): self._key_map[k] = v if v not in self._value_groups: self._value_groups[v] = set() self._value_groups[v].add(k) def __getitem__(self, key): if key not in self._key_map: raise KeyError(key) return self._key_map[key] def __setitem__(self, key, value): # 键已存在时先从旧值分组中移除 if key in self._key_map: old_val = self._key_map[key] self._value_groups[old_val].remove(key) if not self._value_groups[old_val]: del self._value_groups[old_val] # 更新为新的映射关系 self._key_map[key] = value if value not in self._value_groups: self._value_groups[value] = set() self._value_groups[value].add(key) def update_group_value(self, old_value, new_value): # 批量修改所有对应old_value的键的值 if old_value not in self._value_groups: raise ValueError(f"不存在值为{old_value}的分组") if old_value == new_value: return # 取出关联键集合 keys = self._value_groups.pop(old_value) # 更新单键映射 for k in keys: self._key_map[k] = new_value # 合并到新值的分组 if new_value in self._value_groups: self._value_groups[new_value].update(keys) else: self._value_groups[new_value] = keys # 导出题目要求的{键元组: 值}压缩结构 def export_compressed(self): return {tuple(keys): v for v, keys in self._value_groups.items()}
使用示例
# 传入原始字典初始化 d = GroupedValueDict({'a': 'X', 'b': 'X', 'c': 'X', 'd': 'X', 'e': 'X', 'f': 'Z'}) # 兼容普通字典的访问方式 print(d['a'] == 'X') # 输出 True print(d['f'] == 'Z') # 输出 True # 一处修改全量同值生效 d.update_group_value('X', '新的长文本内容') print(d['a'] == '新的长文本内容') # 输出 True print(d['b'] == '新的长文本内容') # 输出 True print(d['c'] == '新的长文本内容') # 输出 True # 导出压缩结构 compressed = d.export_compressed() print(compressed) # 输出:{('a', 'b', 'c', 'd', 'e'): '新的长文本内容', ('f',): 'Z'}
补充说明
- 如果存储的长文本是可变对象(如列表、自定义类实例),无需调用
update_group_value,直接修改值本身就会对所有关联键生效,因为所有键指向的是同一个内存地址的对象。 - 如需完全兼容原生
dict的所有内置方法,可以根据需求补充重写__contains__、keys、values、items等魔术方法,上述示例已经覆盖核心的访问和批量更新需求。
内容的提问来源于stack exchange,提问作者PaxPrz
相关产品推荐
相关产品推荐

