我正在尝试从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]
我删除了将采用元素和列表的代码,并返回列表,其中列表中删除了该元素。因此我尝试将其合并到我的删除重复方法中,但我并不太了解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).
我错过了什么?
答案 0 :(得分:7)
% 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).
答案 1 :(得分:2)
您发布的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
以隐藏谓词用户的第三个参数。