如何在Prolog列表中打包元组的元素



假设我有一个列表:

Os = [(4,P1),(9,P2),(4,P3),(1,P4),(9,P5)].

我想把元组的第二个元素放在一个袋子里,这个袋子有相同的第一个元素,像这样:

SortedOs = [(4,[P1,P3]),(9,[P2,P5]),(1,P4)].

目前我使用的是bagof/3:

findall(
(O,Bag),
bagof(P,member((O,P),Os),Bag),
SortedOs
).

但是它给了我排序列表,像这样:

SortedOs = [(1,P4),(4,[P1,P3]),(9,[P2,P5])]

表示bagof/3按升序查找第一个元素。有什么办法可以让我改变这个来得到我想要的列表吗?多谢。

如果您正在使用wi - prolog,并且您可以将数据的格式从元组更改为成对,(Key-Value)然后您可以使用group_pairs_by_key/2。

注意,要使group_pairs_by_key/2正常工作,必须对输入列表进行排序。

代码
example(Pairs0,Result) :-
sort(Pairs0,Pairs1),
group_pairs_by_key(Pairs1,Result).

范例用法
?- Pairs = [4-P1,9-P2,4-P3,1-P4,9-P5],example(Pairs,Result).
Pairs = [4-P1, 9-P2, 4-P3, 1-P4, 9-P5],
Result = [1-[P4], 4-[P1, P3], 9-[P2, P5]].

SWI-Prolog有一个用于处理有序集合(排序列表)的谓词库。ordersets .pl——有序集合操作

检查输入是否是有序集,如果是有序集则跳过排序。

example(List,Result) :-
(
is_ordset(List)
->
Order_set = List
;
list_to_ord_set(List,Order_set)
),
group_pairs_by_key(Order_set,Result).

范例用法
?- List = [1-P4, 4-P1, 4-P3, 9-P2, 9-P5],example(List,Result).
List = [1-P4, 4-P1, 4-P3, 9-P2, 9-P5],
Result = [1-[P4], 4-[P1, P3], 9-[P2, P5]].
?- List = [4-P1,9-P2,4-P3,1-P4,9-P5],example(List,Result).
List = [4-P1, 9-P2, 4-P3, 1-P4, 9-P5],
Result = [1-[P4], 4-[P1, P3], 9-[P2, P5]].

注意:有序集删除重复项,所以使用list_to_ord_set/2代替sort/2将删除重复项。

?- List = [4-P1,4-P1,9-P2,4-P3,1-P4,9-P5],example(List,Result).
List = [4-P1, 4-P1, 9-P2, 4-P3, 1-P4, 9-P5],
Result = [1-[P4], 4-[P1, P3], 9-[P2, P5]].

group_pairs_by_key/2(源代码)

最新更新