You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:09:47