Prolog中如何合并两个字典并对相同键的值求和?
SWI-Prolog 字典合并谓词实现
你要实现的同标签计数字典合并效果(同键值相加、独有键保留),不需要套用命令式语言的for循环思路——Prolog是声明式语言,你只需要描述清楚合并规则,用内置的列表、字典操作谓词即可实现。
完整实现代码
% 合并两个同标签的计数字典,同键对应数值求和 merge(Dict1, Dict2, Merged) :- % 校验两个输入均为字典,且标签一致 is_dict(Dict1, DictTag), is_dict(Dict2, DictTag), % 分别提取两个字典的键列表 dict_keys(Dict1, Keys1), dict_keys(Dict2, Keys2), % 拼接键列表后去重,得到所有需要保留的键 append(Keys1, Keys2, DupKeys), sort(DupKeys, AllKeys), % 对每个键计算合并后的值,生成键值对列表 maplist(build_kv(Dict1, Dict2), AllKeys, KVPairs), % 用原标签和键值对生成最终合并字典 dict_create(Merged, DictTag, KVPairs). % 单个键的合并逻辑:键不存在时值按0计算,两个字典的值相加 build_kv(D1, D2, Key, Key-TotalVal) :- TotalVal is D1.get(Key, 0) + D2.get(Key, 0).
效果验证
加载上述代码后运行你给出的查询,会得到完全符合预期的结果:
?- merge(counter{a: 1, b: 2}, counter{a: 3, c: 4, d: 5}, Merged). Merged = counter{a: 4, b: 2, c: 4, d: 5}.
思路说明
你之前用for循环思路失败的核心原因是:逻辑编程没有命令式语言里的可变变量、循环计数器、逐行执行的流程控制,你不需要手动维护临时变量、遍历修改值,只需要明确描述「合并结果满足什么规则」即可:
- 合并后的字典标签和两个输入字典一致
- 合并后的字典包含两个输入字典的所有键
- 每个键对应的值,是两个字典中该键对应值的和,不存在的键按0计数
代码里用到的几个核心内置谓词作用:
is_dict/2:校验输入是字典类型,同时提取字典的标签(比如示例里的counter)dict_keys/2:提取字典所有键组成的列表sort/2:对列表排序同时自动去重,刚好得到无重复的完整键列表maplist/3:将单键合并规则应用到整个键列表上,是逻辑编程里替代手动for循环的常用方式dict_create/3:根据标签和键值对列表生成最终的字典结构- 字典的
.get(Key, Default)语法:读取键对应的值,键不存在时返回指定默认值,刚好适配计数器的求和逻辑
内容的提问来源于stack exchange,提问作者wooseop
相关产品推荐
相关产品推荐

