在Prolog中按谓词第三个参数将列表拆分为列表的列表
按谓词第三个参数分组列表元素
我有如下谓词列表:
[patient(204,4,2),patient(203,3,2),patient(303,7,3),patient(302,6,3),patient(404,12,4),patient(403,11,4),patient(504,16,5),patient(503,15,5)]
需要根据每个patient/3谓词的第三个参数,将列表转换为嵌套列表,预期结果如下:
[ [patient(204,4,2),patient(203,3,2)] , [patient(303,7,3),patient(302,6,3)] , [patient(404,12,4),patient(403,11,4)] , [patient(504,16,5),patient(503,15,5)] ]
实现方案
方案1:使用内置谓词(推荐)
借助Prolog内置的group_pairs_by_key/2可以高效完成分组,步骤如下:
- 将每个
patient/3元素转换为键-值对,键取第三个参数,值为元素本身 - 用
group_pairs_by_key/2按键分组 - 提取每个分组的元素列表
代码实现:
group_by_third_arg(Patients, Grouped) :- maplist(patient_to_pair, Patients, Pairs), group_pairs_by_key(Pairs, KeyGroups), maplist(extract_group, KeyGroups, Grouped). patient_to_pair(patient(A,B,C), C-patient(A,B,C)). extract_group(_-Group, Group).
测试调用:
?- group_by_third_arg([patient(204,4,2),patient(203,3,2),patient(303,7,3),patient(302,6,3),patient(404,12,4),patient(403,11,4),patient(504,16,5),patient(503,15,5)], G). G = [[patient(204, 4, 2), patient(203, 3, 2)], [patient(303, 7, 3), patient(302, 6, 3)], [patient(404, 12, 4), patient(403, 11, 4)], [patient(504, 16, 5), patient(503, 15, 5)]].
方案2:手动实现分组逻辑
如果你的Prolog环境没有group_pairs_by_key/2,可以手动实现递归分组:
group_by_third_arg([], []). group_by_third_arg([Patient|Rest], [Group|GroupedRest]) :- Patient = patient(_,_,Key), findall(P, (member(P, [Patient|Rest]), P = patient(_,_,Key)), Group), subtract([Patient|Rest], Group, Remaining), group_by_third_arg(Remaining, GroupedRest).
这个版本通过findall/3收集所有同键的元素,再用subtract/3移除已分组元素,递归处理剩余列表。
内容的提问来源于stack exchange,提问作者elfii
相关产品推荐
相关产品推荐

