我需要一个查询,它会从列表中删除所有变量和重复项。
示例:
?- L = [1,2,3,X,Y,3,2], my_awesome_predicate(L, Res).
然后,Res应该是:[1,2,3]。
我不关心秩序(可能是[2,3,1],[3,2,1]或其他)。
不幸的是,我有一个任务,我必须关心效率,所以我的主要问题是 - 它可以更快地完成吗?目前,我有以下代码:
remove_variables([], []).
remove_variables([H|List], Res):- var(H), !, remove_variables(List, Res).
remove_variables([H|List], [H|Res]):- remove_variables(List, Res).
my_awesome_predicate([], []).
my_awesome_predicate(List, Res):-
sort(List, Sorted),
remove_variables(Sorted, Res).
答案 0 :(得分:2)
如果您正在使用 SWI ,那么您可以使用此代码进一步改进:
my_awesome_predicate(List, Res):-
sort(List, MRes),
remove_variables(MRes, Res).
remove_variables([Var|Tail], NTail):-
var(Var),
!,
remove_variables(Tail, NTail).
remove_variables(Res, Res).
因为似乎SWI的排序将首先留下无界变量(不知道这种行为是否是其他prolog的标准),所以你可以在找到第一个非变量后停止删除变量。
读一点SWI's documentation,声明:
4.7.1 Standard Order of Terms
Comparison and unification of arbitrary terms. Terms are ordered in
the so called ``standard order''. This order is defined as follows:
1. Variables < Numbers < Atoms < Strings < Compound Terms
因此,当您找到第一个非变量...
时,停止删除元素似乎是安全的答案 1 :(得分:1)
awesome([],[]).
awesome([H|T],R):- var(H), !, awesome(T,R).
awesome([H|T],R):- awesome(T,[H],R).
awesome([],R,R).
awesome([H|T],A,R):- memberchk(H,A) -> awesome(T,A,R) ; awesome(T,[H|A],R).
这样的东西?从理论上讲它是二次的,但是你的列表很短,而且这段代码非常简单,所以编译器可能会更好地优化它们。
如果附加结果列表,最好更改它以使用差异列表,将输出直接放入正在构建的结果列表中:
awesome([],Z,Z).
awesome([H|T],R,Z):- var(H), !, awesome(T,R,Z).
awesome([H|T],R,Z):- R=[H|Y], awesome(T,[H],Y,Z).
awesome([],_,Z,Z).
awesome([H|T],A,R,Z):- memberchk(H,A) -> awesome(T,A,R,Z)
; R=[H|Y], awesome(T,[H|A],Y,Z).
memberchk/2
当然会清除变量和重复项。
答案 2 :(得分:0)
这是一个古老的问题,但是作为参考,还有一个使用setof
的不错的简短解决方案。
my_awesome_predicate(L, Res) :-
setof(X, (member(X, L), ground(X)), Res).
Res
包含不带变量的解决方案,其变量按其首次出现的顺序排列。
?- my_awesome_predicate([1,2,3,X,Y,3,2], Res).
Res = [1, 2, 3].