2013-11-28 88 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