Prolog:删除重复项

时间:2013-11-28 02:28:06

标签: 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).

但那会占用我的清单并返回[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).

我错过了什么?

2 个答案:

答案 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以隐藏谓词用户的第三个参数。

Demo on ideone.