swi-prolog:如何按子列表的NTH元素对列表进行排序,允许重复

时间:2014-08-04 17:17:07

标签: list sorting prolog

(我使用'asserta'将一个包含多个列的大型csv文件放入数据库中。)有没有办法按列进行数字排序而不删除重复项?

从我的简单示例(按第二列/元素排序)中可以看到,predsort方法删除了重复项。

我可以通过切换和删除一些列并使用msort来解决这个问题,但是我在这里特别要求您提供替代方案。

非常感谢任何建议!

mycompare(X,E1,E2):- 
E1=[_,A1],E2=[_,A2],compare(X, A1, A2).

?- predsort(mycompare,[ [[95, 97], 11], [[97, 99], 4], [[97, 98], 4]],X).
X = [[[97, 99], 4], [[95, 97], 11]].

?- msort([ [[95, 97], 11], [[97, 99], 4], [[97, 98], 4]],X).
X = [[[95, 97], 11], [[97, 98], 4], [[97, 99], 4]].

%What I want is:
?- wanted_sort(...<as above>...).
X = [[[97, 98], 4], [[97, 99], 4], [[95, 97], 11] ].

2 个答案:

答案 0 :(得分:2)

执行此操作的标准方法是使用keysort/2。首先,您首先相应地映射元素,然后键入,并映射回值。

list_pairs([], []).
list_pairs([E|Es], [B-E|Ps]) :-
   E = [_,B],
   list_pairs(Es, Ps).

pairs_values([], []).
pairs_values([_-V|Ps], [V|Vs]) :-
   pairs_values(Ps, Vs).

andrew_sort(Xs, Ys) :-
   list_pairs(Xs, Ps),
   keysort(Ps, PsS),
   pairs_values(PsS, Ys).

对于keysort/2的其他用途,请参阅this list

答案 1 :(得分:2)

Imho predsort / 3提供了一种非常通用且相当有效的方法 - 它就像避免从比较谓词中返回=一样简单。例如:

?- [user].
|: comparer(<, A, B) :- A @< B.
|: comparer(>, _, _).
(^D here)
true.

?- predsort(comparer, [1,2,1,a,b,a], L).
L = [1, 1, 2, a, a, b].

您的测试用例:

mycompare(<,[_,A1|_],[_,A2|_]) :- A1 < A2.
mycompare(>, _, _).

产量

?- predsort(mycompare,[ [[95, 97], 11], [[97, 99], 4], [[97, 98], 4]],X).
X = [[[97, 98], 4], [[97, 99], 4], [[95, 97], 11]].

我略微概括了匹配的模式,从[_,N][_,N|_] ...

编辑:很有趣,我没看过标题 ... 概括比较第n个参数:

?- predsort(nthcompare(2),[ [[95, 97], 11], [[97, 99], 4], [[97, 98], 4]],X).
X = [[[97, 98], 4], [[97, 99], 4], [[95, 97], 11]].

和nthcompare / 4本身:

nthcompare(N,<,A,B) :- nth1(N,A,X),nth1(N,B,Y), X @< Y.
nthcompare(_,>,_,_).

那是......