仅查找不在两个列表中的唯一元素

时间:2011-05-17 18:52:09

标签: prolog

计算两个列表的对称差异,并返回不包含重复项的第三个列表。

显示预期结果的示例查询:

?- join([a,b,p,l,a,f],[q,a,z,x,l],Rs).
Rs = [b,p,f,q,z,x].

我目前有这段代码:

join([],List,List).
join([H|T],List,[H|Result]) :-
    not(member(H,List)),
    join(T,List,Result).
join([H|T],Y,Z) :-
    join(T,Y,Z).

它可以找到所有不重复的元素,但它将它们全部作为头部放在第二个列表中。

我怎样才能这样做,以便第二个列表也检查重复的元素,只输出那些不重复的元素?

3 个答案:

答案 0 :(得分:2)

您描述的“非交集”似乎是两组的对称差异,这是它们(非对称)集合差异的并集。可以使用SWI-Prolog subtract/3谓词或this problem解决方案计算差异。

可以使用append/3后跟sort/2来完成联合,后者会处理重复项。

答案 1 :(得分:1)

以下实施保留。它基于:

让我们直接看看代码!

list_list_symdiffset([],Ys,Zs) :-
   list_setB(Ys,Zs).
list_list_symdiffset([X|Xs0],Ys0,Zs0) :-
   tpartition(=(X),Ys0,Es,Ys1),
   if_(Es=[], Zs0=[X|Zs1], Zs0=Zs1),
   tfilter(not_t(=(X)),Xs0,Xs1),
   list_list_symdiffset(Xs1,Ys1,Zs1).

让我们运行OP给出的示例查询:

?- list_list_symdiffset([a,b,p,l,a,f],[q,a,z,x,l],Rs).
Rs = [b,p,f,q,z,x].                   % succeeds deterministically

最后,让我们尝试一些更通用的东西!

?- list_list_symdiffset([A,B],[X,Y],Ys).
Ys = [],        A=B, B=X, X=Y ;
Ys = [B],       A=X, X=Y, dif(Y,B) ;
Ys = [Y],       A=B, B=X, dif(X,Y) ;
Ys = [],        A=X, B=Y, dif(X,Y), dif(X,Y) ;
Ys = [B,Y],     A=X, dif(X,B), dif(X,Y), dif(B,Y) ;
Ys = [X],       A=B, B=Y, dif(Y,X) ;
Ys = [],        A=Y, B=X, dif(Y,X), dif(Y,X) ;
Ys = [B,X],     A=Y, dif(Y,B), dif(Y,X), dif(B,X) ;
Ys = [B,Y],     A=B, X = Y, dif(B,Y), dif(B,Y) ;
Ys = [B,X,Y],   A=B, dif(B,Y), dif(B,X), dif(X,Y) ;
Ys = [A],       B=X, X=Y, dif(A,Y), dif(A,Y),dif(A,Y) ;
Ys = [A,Y],     B=X, dif(A,X), dif(A,Y), dif(A,X), dif(X,Y) ;
Ys = [A,X],     B=Y, dif(A,Y), dif(A,Y), dif(A,X), dif(Y,X) ;
Ys = [A,B,Y],   X=Y, dif(A,B), dif(A,Y), dif(A,Y), dif(B,Y), dif(B,Y) ;
Ys = [A,B,X,Y], dif(A,B), dif(A,Y), dif(A,X), dif(B,Y), dif(B,X), dif(X,Y).

答案 2 :(得分:0)


join(L1,L2,L) :-
        append(L1,L2,L3),
        findall(A,unique(L3,A),L).

unique(L3,A) :-
        append(L0,[A|R],L3),
        \+(append(_,[A|_],L0)).