2016-05-03 37 views
3

所以基本上我的任務是創建一個給定列表的集合,其中包含一個包含2個參數的謂詞。從Prolog中的列表創建一個集合

第一個是列表,第二個是Set的值。

但是不知它給了我其中包含設置作爲頭具有可變A尾巴列表:

2 ?- list2set([2,3,4,4] , X). 
X = [2, 3, 4|_G2840] . 

多數民衆贊成代碼:

list2set([] , _). 
list2set([ListH|ListT] , Set) :- member(ListH, Set) , list2set(ListT , Set). 

這似乎是一個很基本的我犯的錯。

+0

是什麼使定義中的集合成爲一個集合?你只是想要一個具有獨特元素的列表?要成爲傳統定義的「集合」意味着元素的排序無關緊要,而且它們都是獨一無二的。只有當您考慮要在該集上執行什麼操作時,元素的排序纔會變得有意義。 – lurker

+0

Set是一種代數數據類型,其對象配有一個函數,該函數給出一個對象測試對象是否在Set中,或不在O(1)處。實質上它是一個哈希映射,其鍵未被使用。列表具有O(n)最差情況下的查找時間,並且通常通過不連續的分配鏈接來保證緩存未命中。對於一個集合來說,它必須被分攤到O(1)訪問時間。 – Dmitry

回答

1

好的方式來填充一個唯一的列表,保持開放式。

您可以用呼叫length(Set, _),或手工編碼當量(使其確定性,太)關閉它,當你完成:

list2set([], S):- 
    % length(S, _), ! 
    close_it(S).   % use var/1 

此外,考慮調用memberchk/2代替member/2

你也可以給一個「聰明」的答案,通過定義

list2set(X, X). 

,並說,你允許你的套表示重複。

2

首先,在Prolog中沒有設置。我們只列出了。所以你可以做的是將一個列表與重複元素關聯到一個沒有列表的列表。 list_nub/2就是這樣一個定義。

要在當前的定義:

已經list2set([], [a])成功,這不可能是正確的。所以你的定義太籠統了。您需要用list2set([],[])替換list2set([],_)。然後,用member(ListH,ListT)代替member(ListH, Set)

而你需要的情況下,另一種治所在元素不存在:

list2set([] , []). 
list2set([E|Es] , Set) :- 
    member(E, Es) , 
    list2set(Es , Set). 
list2set([E|Es] , [E|Set]) :- 
    maplist(dif(E), Es), 
    list2set(Es , Set). 

避免重複回答一個更緊湊的定義是list_nub/2


1)嚴格意義上講,人們可以通過歸因變量擴展統一實施ACI -unification有真正的套。

2)我的—粗—瞭解這將需要執行SICStus中的屬性變量。其他接口,如SWI或YAP中的當前接口很可能不夠用;因爲他們已經是CLP(B)。有關更多信息,請參閱this discussion