Example how to use predsort(:Compare, +List, -Sort

2019-04-10 10:15发布

I want to order a custom list. The list I want to order will be in this form...

[n(_,2,_),n(_,1,_),n(_,3,_)]  

I have wrote a comparator

cheaper(n(_,C1,_),n(_,C2,_)) :-
        C1>C2.  

How do I use this with predsort. I wrote a sorting algorithm using bubble sort, but I have very large lists so it very slow.

Is it possible to do

predsort(cheaper, [n(_,2,_),n(_,1,_),n(_,3,_)] , X).

Thank you :)

3条回答
甜甜的少女心
2楼-- · 2019-04-10 11:03

Try to avoid using predsort/3. This is an SWI-specific predicate that is not particularly efficient, because all ~ O(n log n) comparisons are executed by calling your definition. Rather try to use keysort/2 which is a standard predicate and which does not incur any such call overhead:

So first map your list Ns to a list of pairs KNs, then sort, and then extract the values.

n_pricep(N, C-N) :-
   N = n(_,C,_).

pair_value(_-V,V).

   ...,
   maplist(n_pricep, Ns, KNs),
   keysort(KNs, KNsS),
   maplist(pair_value, KNsS, NsS).
查看更多
乱世女痞
3楼-- · 2019-04-10 11:04

Try this :

cheaper(>, n(_,C1,_),n(_,C2,_)) :-
        C1>C2.

cheaper(<, n(_,C1,_),n(_,C2,_)) :-
        C1<C2.

cheaper(=, n(_,C1,_),n(_,C2,_)) :-
        C1=C2.

Be aware that predsort works like sort, there are no doubles ! If you want to keep doubles, try

cheaper(>, n(_,C1,_),n(_,C2,_)) :-
        C1>C2.

cheaper(<, n(_,C1,_),n(_,C2,_)) :-
        C1=<C2.
查看更多
看我几分像从前
4楼-- · 2019-04-10 11:11

Joel has shown the basic case (+1), but to get better performance, avoid repeating the test:

cheaper(R, n(_,C1,_),n(_,C2,_)) :-
        C1>C2 -> R = > ; R = < .

edit

Now SWI-Prolog has another builtin sort/4, that for simple cases avoids the penalties related to calls of user defined predicates:

?- sort(2,@=<,[n(_,2,_),n(_,1,_),n(_,3,_)],S).
S = [n(_2578, 1, _2582), n(_2564, 2, _2568), n(_2592, 3, _2596)].
查看更多
登录 后发表回答