从Prolog中的列表创建集合

时间:2016-05-03 21:32:03

标签: list prolog

所以基本上我的任务是创建一个给定List的Set,其中谓词包含2个参数。

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

但不知何故,它给了我一个List,其中包含Set作为Head和带有变量的Tail:

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

那就是代码:

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

这似乎是我犯的一个非常基本的错误。

3 个答案:

答案 0 :(得分:2)

首先,Prolog中没有套装。我们只列出 1 。因此,您可以做的是将列表与重复元素关联到列表中。 list_nub/2就是这样一个定义。

根据您目前的定义:

已经list2set([], [a])成功,这是不对的。所以你的定义太笼统了。您需要将list2set([],_)替换为list2set([],[])

然后,将member(ListH, Set)替换为member(ListH,ListT)

对于元素不存在的情况,您需要另一条规则:

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)严格来说,可以通过属性变量 2 扩展统一来实现ACI - 统一以拥有真实集合。

2)对于我的粗略理解,这需要在SICStus中实现属性变量。其他接口,如SWI或YAP中的电流很可能不足;因为他们已经为CLP(B)。有关详情,请参阅this discussion

答案 1 :(得分:1)

填充唯一列表的好方法,保持开放性。

完成后,您可以通过电话length(Set, _)或手动编码的等效电子邮件将其关闭(也可以将其设置为确定性的):

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

另外,请考虑拨打memberchk/2而不是member/2

您还可以通过定义

来提供“智能”答案
list2set(X, X).

并且说你允许在集合的表示中重复。

答案 2 :(得分:0)

这里是仅使用member / 2的定义。

% base case
set([], []).
% here we say that if the head is in the tail of the list
% we discard the head and create a set with the tail
% the exclamation mark is a "cut" which means that if member(H, T) was true
% prolog cannot backtrack from set([H|T], X) to set([H|T], [H|X]).
% this prevents giving extra answers that aren't sets, try removing it. 
set([H|T], X):- member(H, T), !, set(T, X).
% and here we say that if the previous clause didn't match because
% head is not a member of tail then we create a set of the tail adding head.
set([H|T], [H|X]):- set(T, X).

希望有帮助!