如何在Swi Prolog中对元组列表排序

如何在Swi Prolog中对元组列表排序,prolog,prolog-setof,Prolog,Prolog Setof,我在swi prolog中有这样一个列表: [(5,4), (1,4), (3,12), (4,2), (5,4)] [(4,2), (1,4), (5,4), (3,12)] 我需要按每个元组的第二个元素组织列表,删除任何重复的元素,因此此列表如下所示: [(5,4), (1,4), (3,12), (4,2), (5,4)] [(4,2), (1,4), (5,4), (3,12)] 使用谓词sort/2,它完成了我想要的一切,除了它根据每个元组的第一个元素进行组织之外,我不希望这样

我在swi prolog中有这样一个列表:

[(5,4), (1,4), (3,12), (4,2), (5,4)]
[(4,2), (1,4), (5,4), (3,12)]
我需要按每个元组的第二个元素组织列表,删除任何重复的元素,因此此列表如下所示:

[(5,4), (1,4), (3,12), (4,2), (5,4)]
[(4,2), (1,4), (5,4), (3,12)]
使用谓词sort/2,它完成了我想要的一切,除了它根据每个元组的第一个元素进行组织之外,我不希望这样

我怎么做

受此启发,我修改了pivot算法以满足您的需要。我在Sicstus Prolog上进行了测试,它成功了

:- use_module(library(lists)).

pivoting(_,[],[],[]).
pivoting((A,B),[(C,D)|T],[(C,D)|L],G):-D>B,pivoting((A,B),T,L,G).
pivoting((A,B),[(C,D)|T],[(C,D)|L],G):-D=B,C>A,pivoting((A,B),T,L,G).
pivoting((A,B),[(C,D)|T],L,[(C,D)|G]):-D<B,pivoting((A,B),T,L,G).
pivoting((A,B),[(C,D)|T],L,[(C,D)|G]):-D=B,C<A,pivoting((A,B),T,L,G).
pivoting((A,B),[(C,D)|T],L,G):-A=C,D=B,pivoting((A,B),T,L,G).

quick_sort(List,Sorted):-q_sort(List,[],Sorted).
q_sort([],Acc,Acc).
q_sort([H|T],Acc,Sorted):-
    pivoting(H,T,L1,L2),
    q_sort(L1,Acc,Sorted1),q_sort(L2,[H|Sorted1],Sorted).

如果您不想编写自己的排序例程,那么您的Prolog排序可能比您的排序更优化,您可以使用一些特定于实现的谓词来比较您的选择

例如,SWI Prolog有predsort/3,它接受一个谓词进行排序。您可以将其与一个谓词一起使用,该谓词首先对一对中的第二个元素进行比较:

compare_by_second(<, (A, B), (C, D)) :-
    (   B @< D
    ;   B == D,
        A @< C ).
compare_by_second(=, (A, B), (C, D)) :-
    A == C,
    B == D.
compare_by_second(>, (A, B), (C, D)) :-
    (   B @> D
    ;   B == D,
        A @> C ).

% ?- predsort(compare_by_second, [(5,4), (1,4), (3,12), (4,2), (5,4)], Sorted).
%@ Sorted = [ (4, 2), (1, 4), (5, 4), (3, 12)] ;
%@ false.

@Sam没问题,你应该检查Isabelle Newbie的答案,因为它看起来更干净,可能更有效率。