2013-11-28 47 views
5

我想从序言中的列表中删除重复的条目。因此,列表[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]

我删除代码,将采取元素和列表,并返回一个列表列表中该元素的出现被删除。所以我试图将其纳入我的删除重复的方法,但我不太了解序言非常好,所以它不工作。从逻辑上讲,我希望在新列表中使用递归调用的头部减去头部的所有事件。这是代码在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)); 

原来这就是我试图在序言

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). 

我缺少什么?

回答

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). 
+0

谢谢SQB,这正是我想要做的逻辑。即使在查看您的代码时,我似乎也无法找到我犯了错误的地方,但他们对我也一样。然而,你的工作,我的卡在一个无限循环。 – user3043403

+0

嗯,我想我想通了,订单内: - 是重要的,所以我的线。 remvdub([H | T],[H | Ans]): - remvdub(Ans1,Ans),remv(H,T,Ans1)。应该是remvdub([H | T],[H | Ans]): - remv(H,T,Ans1),remvdub(Ans1,Ans)。 – user3043403

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.

+0

感谢dasblinkenlight,即工作!出于好奇,是否有办法做到我在底层代码块中尝试的内容?我在哪里使用删除代码来插入头部和重复头部的渐进式小列表中删除? – user3043403

+0

@ user3043403我不明白sml,所以我无法理解工作原型代码。然而,'remvdub/2'谓词的第二个子句看起来非常可疑,因为它看起来像进入了无限递归。 – dasblinkenlight