Найти только уникальные элементы, которых нет в обоих списках - PullRequest
2 голосов
/ 17 мая 2011

Вычислить симметричную разность двух списков и вернуть третий список, не содержащий дубликатов.

Пример запроса с ожидаемыми результатами:

?- 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 ]

2 голосов
/ 17 мая 2011

Кажется, что описываемое вами «непересекающееся» является симметричной разностью двух множеств, которая представляет собой объединение их (асимметричных) разностей множеств.Разница в наборе может быть вычислена с помощью предиката SWI-Prolog subtract/3 или решения этой проблемы .

Получение объединения может быть выполнено с помощью append/3, за которым следует sort/2, чтозаботится о дубликатах.

1 голос
/ 16 июня 2015

Следующая реализация сохраняет . Он основан на:

  • мета-предикаты tfilter/3 и tpartition/4,
  • монотонная управляющая конструкция if-then-else if_/3,
  • Унифицированная унарная логическая связка not_t/3,
  • уточненный термин предикат равенства (=)/3,
  • и чистый предикат "list to set" list_setB/2, определенный в предыдущий ответ .

Давайте перейдем прямо к коду!

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).
0 голосов
/ 18 мая 2011

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)).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...