Prolog 序言:删除重复项

Prolog 序言:删除重复项,prolog,Prolog,我试图从prolog中的列表中删除重复的条目。所以列表[a,b,a,c,b,a]将返回[a,b,c]。我不能使用任何内置函数。我在这里搜索并找到了这个代码 member(X,[X|_]) :- !. member(X,[_|T]) :- member(X,T). set([],[]). set([H|T],[H|Out]) :- not(member(H,T)), set(T,Out). set([H|T],Out) :- member(H,T), set(T,Out). 但这会占用我的列表并

我试图从prolog中的列表中删除重复的条目。所以列表[a,b,a,c,b,a]将返回[a,b,c]。我不能使用任何内置函数。我在这里搜索并找到了这个代码

member(X,[X|_]) :- !.
member(X,[_|T]) :- member(X,T).
set([],[]).
set([H|T],[H|Out]) :- not(member(H,T)), set(T,Out).
set([H|T],Out) :- member(H,T), set(T,Out).
但这会占用我的列表并返回[c,b,a]而不是[a,b,c]

我有一个删除代码,该代码将获取一个元素和一个列表,并返回一个列表,其中该元素在列表中的引用已被删除。所以我尝试将它合并到我的remove-replicate方法中,但我对prolog不是很了解,所以它不起作用。从逻辑上讲,我想用对新列表的递归调用减去所有出现的头部的列表。这就是sml中的代码

fun remv(_,nil) = nil
|   remv(a,x::xs) = if x=a then remv(a,xs) else x::remv(a,xs);
fun remvdub (nil) = nil
|   remvdub(x::xs) = x::remvdub(remv(x,xs)); 
这就是我在prolog中尝试的

remv(_,[],[]).
remv(X,[X|T],Ans) :- remv(X,T,Ans).
remv(X,[H|T],[H|K]) :- remv(X,T,K). 

remvdub([],[]).
remvdub([H|T],[H|Ans]) :- remvdub(Ans1,Ans), remv(H,T,Ans1).

我遗漏了什么?

您发布的Prolog代码片段在逻辑上是正确的。如果要保留每个重复项的第一个副本(而不是最后一个副本),可以按如下方式更改代码:

member(X,[X|_]) :- !.
member(X,[_|T]) :- member(X,T).
set(A,B) :- set(A, B, []).
set([],[],_).
set([H|T],[H|Out],Seen) :- not(member(H,Seen)), set(T,Out, [H|Seen]).
set([H|T],Out, Seen) :- member(H,Seen), set(T,Out,Seen).
我们的想法是添加第三个参数,它表示到目前为止看到的项目列表,并根据它检查成员资格,而不是根据剩余的列表检查成员资格。请注意,添加
set/2
是为了对谓词的用户隐藏第三个参数


谢谢dasblinkenlight,它成功了!出于好奇,有没有一种方法可以实现我在底层代码块中尝试的功能?我在哪里使用删除代码插入带有删除头和重复头的渐进较小列表?@user3043403我不理解sml,所以我无法理解工作原型代码。然而,
remvdub/2
谓词的第二个子句看起来非常可疑,因为它看起来像是进入无限递归。感谢SQB,这正是我试图做的逻辑。即使在查看您的代码时,我似乎也找不到我犯错误的地方,他们也向我读了同样的内容。然而你的有效,而我的却陷入了一个内因循环。嗯,我想我明白了,在:-内的顺序很重要,所以我的路线。remvdub([H | T],[H | Ans]):-remvdub(Ans1,Ans),remv(H,T,Ans1)。应该是remvdub([H | T],[H | Ans]):-remv(H,T,Ans1),remvdub(Ans1,Ans)。
% An empty list is a set.
set([], []).

% Put the head in the result,
% remove all occurrences of the head from the tail,
% make a set out of that.
set([H|T], [H|T1]) :- 
    remv(H, T, T2),
    set(T2, T1).

% Removing anything from an empty list yields an empty list.
remv(_, [], []).

% If the head is the element we want to remove,
% do not keep the head and
% remove the element from the tail to get the new list.
remv(X, [X|T], T1) :- remv(X, T, T1).

% If the head is NOT the element we want to remove,
% keep the head and
% remove the element from the tail to get the new tail.
remv(X, [H|T], [H|T1]) :-
    X \= H,
    remv(X, T, T1).