Finding Unique Items in a List

I'm trying to write a rule which decides whether an item X occurs exactly one in a list L.

unique(X, [X|T]):- !, \+ member(X, T).
unique(X, [_|T]):- unique(X, T).

The rule works for determining whether a value is unique within a list or nor, but when I try to get unique values within a list using unique(X, [1,2,3,1,3,2,5,4,3,8]). it returns just false. What I expected is this (like member(X, list).:

X = 5 ;
X = 4 ;
X = 8 ;

I'm a complete beginner and I don't know what I am doing wrong.


  • Here is a simple solution using nth0/4 (or select/3 as pointed out by @false):

    unique(X, L) :-
        nth0(_, L, X, R),
        \+ member(X, R).

    nth0/4 4th argument R is the list L with the element X removed. We simply check then that X is not in R.

    Better version

    unique(X, L) :-
        nth0(_, L, X, R),
        maplist(dif(X), R).

    This fixes the problem pointed out by @false, though since you are a beginner I doubt this is of much interest to you.

    This has the advantage of working in situations like this one:

    ?- unique(b, [X, Y, a]).
    X = b,
    dif(Y, b) ;
    Y = b,
    dif(X, b) ;