Remove shared items in a list in prolog

Viewed 50

I have been trying to program a function that takes two lists, and returns a list of the items from list one that DO NOT APPEAR in the list 2. This is the code I have so far. The road block that I am running into is that I can't figure out how to test false on my member() line.

%remove_them/3
remove_them([H|T],List,[Newhead|NewTail]):-
    not(member(H,List)),
    Newhead is H,
    remove_them(T,List,NewTail).

remove_them([H|T],List,NewList):-
    member(H,List),
    remove_them(T,List,NewList).
1 Answers

You forgot to say when this recursion should end (first line):

remove_them([],_,[]).
remove_them([H|T],List,[H|NewTail]):- 
    \+(member(H,List)), 
    remove_them(T,List,NewTail).
remove_them([H|T],List,NewList):- 
    member(H,List), 
    remove_them(T,List,NewList).

?- remove_them([1,2,e],[a,4,1],L).
L = [2, e] ;
false.

?- remove_them([r,2,3],[a,4,1,e],L).
L = [r, 2, 3] ;
false.

As pointed out from Guy Coder there is also the possibility of ordered sets. In SWI Prolog you can use this functionality to shorten/optimize your code. Please note that duplicates can not appear within sets:

remove_them2(Ori, Minus, Erg):-
    list_to_ord_set(Ori, Sori),
    list_to_ord_set(Minus, Sminus),
    ord_subtract(Sori, Sminus, Erg).

?- remove_them2([r,2,3],[a,4,1,e],L).
L = [2, 3, r].

?- remove_them2([1,2,e],[a,4,1],L).
L = [2, e].

?- remove_them2([a,a,a,b,b],[b,1,2],L).
L = [a].
Related