首页 > 解决方案 > 根据 2 个键对序言中的列表进行排序

问题描述

假设我有这个列表。

A=[(a,1), (b,3), (d,2), (c,2)]

我想根据两件事对其进行排序,首先我检查数字,如果它们相同,我需要按字母进行排序,例如这将被排序为:

S=[(a,1), (c,2), (d,2), (b,3)]

如果我用这个

sort(2, @=<, A, S).

我得到的是排序的列表,但仅基于数字,如何添加该加控件?

标签: sortingprologkey

解决方案


根据sort/4'@=<' 表示“升序排序,但不消除重复”。

如果我们接受重复消除,我们可以使元谓词适应predsort/3我们的需要。

predsort(+Pred, +List, -Sorted)

这只是其他编程语言中已知的“排序方法”的另一种形式。例如,在 Java 中有Collections.sort一个Comparator接口。在这里,predsort/3将谓词名称Pred(或部分填充的谓词调用)作为可调用过程。一样。

谓词compare/3正是我们需要进行元素比较的,因为它使用标准的术语顺序来比较整个术语

?- compare(D,(a,1),(b,3)).
D =  (<).

?- compare(D,(a,1),(a,3)).
D =  (<).

?- compare(D,(a,3),(a,1)).
D =  (>).

?- compare(D,(b,3),(a,1)).
D =  (>).

但是,它首先按第一个子元素进行比较,其次按第二个子元素进行比较(或更准确地说,按具有函子名称的复合项的参数顺序,

所以我们必须先扭转这些。这是通过另一个元maplist/3谓词完成的,其中“将一个列表的元素映射到另一个列表的元素的谓词”将是“反转的谓词”。由于我懒得为此添加单独的谓词,我将使用library(yall):[(C,N),(N,C)]>>true等效于reverse((C,N),(N,C)).

所以:

my_sort(ListIn,ListOut) :-
   maplist([(C,N),(N,C)]>>true,ListIn,List2),
   predsort(compare,List2,List3),
   maplist([(C,N),(N,C)]>>true,ListOut,List3).

所以:

?- my_sort([(a,1), (b,3), (d,2), (c,2)], Out).
Out = [(a, 1),  (c, 2),  (d, 2),  (b, 3)].

请注意,(A,B)成对使用结构不是完美的风格 -,是连词。改用实际的对:(A-B即真正-(A,B)的结构)。

它适用于空列表吗?是的,它确实。

?- my_sort([],[]).
true.

更完整的例子在这里:


推荐阅读