在Prolog中的元组列表中按降序排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Prolog中的元组列表中按降序排序相关的知识,希望对你有一定的参考价值。
我想基于列表的第二个值按降序对元组列表进行排序,而不使用内置的排序谓词。
示例:(Name, Age)
。
unsorted_list = [(mary, 20), (jack, 50), (bob, 16), (bill, 20) ].
sorted_list = [(jack, 50), (bill, 20), (mary, 20), (bob, 16)].
有谁知道这样做的优雅方式?
有很多方法可以实现这一点。一种方法是从头开始实现您的自定义对排序,这样做的好处是您可以确切地知道算法的实现以及复杂性,但这可能不是那么优雅。
另一个更优雅的方法是使用Prolog的ISO谓词keysort/2
,它对[X1-Y1, X2-Y2, ...]
形式的对列表进行排序,并且排序基于对的第一个参数(Xi
)。因此,您需要以[-20-mary, -50-jack, -16-bob, -20-bill]
格式更改列表,然后应用keysort/2
。请注意,由于@ false的注释为了实现降序的稳定解决方案,我们可以否定数字并按升序排序否定数字:
:-use_module(library(clpfd)).
swap_internals((X,Y), Y1-X):- Y1 #= -Y.
pair_sort(L,Sorted):-
maplist(swap_internals, L, L2),
keysort(L2, L3),
maplist(swap_internals, Sorted, L3).
在上面,您使用maplist/3
和swap_internals/2
以适当的形式构建列表,使用keysort/2
对其进行排序,然后再次使用maplist/3
将其更改回来。
例:
?- pair_sort([(mary, 20), (jack, 50), (bob, 16), (bill, 20) ],L).
L = [(jack, 50), (bill, 20), (mary, 20), (bob, 16)].
这是降序的另一种方式,只需使用sort/4
谓词:
sort(2, @>=, L, Sorted).
例:
?- sort(2,@>=, [(mary, 20), (jack, 50), (bob, 16), (bill, 20) ], L).
L = [(jack, 50), (mary, 20), (bill, 20), (bob, 16)].
虽然它不是ISO谓词,但这种方式显然更容易。
编辑
我没有看到“没有使用内置的排序谓词”这个问题的一部分,所以你可以写一个典型的合并排序来改变下面的merge/2
的第3个规则来处理对:
halve([], [], []).
halve([A], [A], []).
halve([A,B|Cs], [A|X], [B|Y]) :- halve(Cs, X, Y).
merge([], Ys, Ys).
merge(Xs, [], Xs).
merge([(X1,X2)|Xs], [(Y1,Y2)|Ys], M) :-
(
X2 > Y2 -> M = [(X1,X2)|Ms], merge(Xs, [(Y1,Y2)|Ys], Ms)
; M = [(Y1,Y2)|Ms], merge([(X1,X2)|Xs], Ys, Ms)
).
mergeSort([], []).
mergeSort([E], [E]).
mergeSort([E1,E2|Es], SL) :-
halve([E1,E2|Es], L1, L2),
mergeSort(L1, SL1),
mergeSort(L2, SL2),
merge(SL1, SL2, SL).
例:
?- mergeSort([(mary, 20), (jack, 50), (bob, 16), (bill, 20) ],L).
L = [(jack, 50), (bill, 20), (mary, 20), (bob, 16)] ;
false.
虽然在原始帖子中请求了非内置实现,但我还是想添加@coder发布的评论,如果你使用的是Swi-Prolog,那么很少有额外的排序谓词:predsort/3
和sort/4
predsort/3
特别有用,因为它允许您指定自定义排序谓词:
compare_tuples_descending('<', (_, X), (_, Y)) :- X > Y, !.
compare_tuples_descending('>', _, _).
sort_tuples_descending(Unsorted, Sorted) :-
predsort(compare_tuples_descending, Unsorted, Sorted).
用法示例:
?- sort_tuples_descending([(mary, 20), (jack, 50), (bob, 16), (bill, 20)], S).
S = [(jack, 50), (bill, 20), (mary, 20), (bob, 16)].
以上是关于在Prolog中的元组列表中按降序排序的主要内容,如果未能解决你的问题,请参考以下文章