需求:实现双键关联、一键删除同步移除的O(1)字典结构
这需求挺精准的——要一个能把两个键绑定到同一个值的映射结构,删其中一个键另一个也得跟着没,还得保证O(1)的效率,每个值只能配俩键,还要分属不同的键组对吧?我给你写了个完全符合要求的实现,咱们一步步看:
实现方案:DualKeyDict
先上代码,注释都写清楚了:
class DualKeyDict: def __init__(self): # 核心映射:键 -> (对应值, 配对键) self._key_map = {} # 两个键组,满足"条目分属不同列表"的需求 self._group_a = set() self._group_b = set() def add_pair(self, key_a, key_b, value): """添加一组关联键和对应值,每个键只能被绑定一次""" if key_a in self._key_map or key_b in self._key_map: raise ValueError("该键已存在于结构中,无法重复绑定") # 互相记录配对关系 self._key_map[key_a] = (value, key_b) self._key_map[key_b] = (value, key_a) # 把两个键分别归入不同的组 self._group_a.add(key_a) self._group_b.add(key_b) def __getitem__(self, key): """通过任意键直接取值,和普通字典用法一致""" return self._key_map[key][0] def pop(self, key): """移除键及其配对键,返回对应值,全程O(1)操作""" if key not in self._key_map: raise KeyError(f"键 {key} 不存在") value, pair_key = self._key_map.pop(key) # 同步删除配对键 if pair_key in self._key_map: self._key_map.pop(pair_key) # 从对应的组中移除两个键 if key in self._group_a: self._group_a.remove(key) self._group_b.remove(pair_key) else: self._group_b.remove(key) self._group_a.remove(pair_key) return value def get_group(self, group_name): """获取指定组的键列表,支持'组a'和'组b'""" if group_name == "a": return list(self._group_a) elif group_name == "b": return list(self._group_b) else: raise ValueError("仅支持传入 'a' 或 'b' 作为组名") def __contains__(self, key): """支持用in判断键是否存在""" return key in self._key_map def __repr__(self): """打印结构时的友好展示""" entry_str = ", ".join([f"{k}: {v[0]}" for k, v in self._key_map.items()]) return f"DualKeyDict({entry_str})"
核心原理
- O(1)操作保障:用字典
_key_map存储每个键对应的「值+配对键」,不管是取值还是删除,都能直接通过键找到关联信息,所有操作都是字典/集合的O(1)操作。 - 双键关联逻辑:添加键对时,两个键互相记录对方的存在,删除其中一个时,直接通过配对键找到另一个并同步删除。
- 分组需求满足:用两个集合
_group_a和_group_b分别存储两组键,通过get_group可以快速获取对应组的所有键列表。
使用示例
# 初始化结构 dkd = DualKeyDict() # 添加一对关联键和用户信息 dkd.add_pair("user_1001", "alice@test.com", {"name": "Alice", "role": "admin"}) # 通过任意键取值 print(dkd["user_1001"]) # 输出: {'name': 'Alice', 'role': 'admin'} print(dkd["alice@test.com"]) # 输出: {'name': 'Alice', 'role': 'admin'} # 获取两组键的列表 print(dkd.get_group("a")) # 输出: ['user_1001'] print(dkd.get_group("b")) # 输出: ['alice@test.com'] # 删除其中一个键,另一个会同步消失 removed_value = dkd.pop("user_1001") print("alice@test.com" in dkd) # 输出: False print(dkd.get_group("a")) # 输出: []
可调整点
如果不需要分组功能,直接删掉_group_a、_group_b和get_group相关代码就行,结构会更轻量化。
内容的提问来源于stack exchange,提问作者Wizard
相关产品推荐
相关产品推荐

