2014-01-10 35 views
0

我有一個列表,比方說X=[a,b,c,d,c,e,d],如何刪除每個字符中的一個,以便唯一的答案仍然是X1=[c,d]如何從序言列表中刪除除重複項以外的所有重複項

我有一堆只有字母的列表,我需要一個命令,如果列表中包含這樣的內容,就會刪除每個單一的一個字母,如果沒有那個字母,就什麼也不做。

我曾嘗試使用selectchk/3,但它只適用於特定情況。

舉例來說,如果我有列表X=[a,b,c,d,d,e,e,f,f,g,h], 我可以寫selectchk(d,X,X1), selectchk(e,X1,X2), selectchk(f,X2,X3)

正如我所說的,針對特定的情況下,這只是工作,但如果我添加一般謂語,讓我們說我有selectchk/3爲每一個字母,但是,例如, 新名單X1=[a,b,c,d,d]我用selectchk(f,X,X3), 命令失敗,並沒有指定下一個列表X3,所以不能運行,這在列表X3檢查字母「G」下一個命令,因爲沒有這樣的清單。如果失敗,是否有可能執行OR命令?

X=[a,a,c,d,d,e] 

selectchk(a,X,X1) OR(如果沒有一個)append([],X,X1),selectchk(b,X1,X2) OR(如果沒有 'B'),append([],X2,X3)

感謝

回答

1

有幾種方法之一可以做到這一點。我認爲selectchk/3形式的解決方案的良好基礎,這實在是「自動化」你試圖做手工,並使用遞歸什麼:

select_each_one(L, R) :- 
    sort(L, PickList), 
    select_each_one(L, PickList, R). 
select_each_one(L, [H|T], R) :- 
    selectchk(H, L, R1), 
    select_each_one(R1, T, R). 
select_each_one(L, [], L). 

sort提供一個「選擇列表」僅包含每個之一原始列表中的元素。然後select_each_one/3謂詞在原始列表的每次迭代中執行selectchk這些元素中的每一個。

?- select_each_one([a,b,c,d,c,e,d], L). 
L = [c, d] ; 
false. 

?- select_each_one([a,b,c,d,d,e,e,f,f,g,h], L). 
L = [d, e, f] ; 
false. 

另一種方法是到列表中超過一個元素一次複製,但跟蹤我們是否見過的元素或不:

select_each_one(L, R) :- 
    select_each_one(L, [], R). 
select_each_one([H|T], Seen, R) :- 
    ( member(H, Seen) 
    -> R = [H|R1], select_each_one(T, Seen, R1) 
    ; select_each_one(T, [H|Seen], R) 
    ). 
select_each_one([], _, []). 
+0

謝謝你,這對我來說非常有幫助,你的解決方案很容易理解,我仍然會更喜歡第一個。 – user3182929