# How to make an efficient difference of sets function?

How to write a nice code that removes all elements from given set A, that occur also in set B? I would like to use DeleteCases[] for this purpose, but have no good idea how to make it efficient.

SetDifference[A_,B_]:=DeleteCases[A, ??? ]


Or to find out if theres a ready to use function already, as in Lists as Sets there is nothing like that mentioned.

• There is Complement but it could be not efficient enough if you know that, for example, A has no duplicates.
– Kuba
Commented Oct 18, 2013 at 10:48

There is an adequate function: Complement, e.g.:

Complement[{a, b, c, d, e}, {a, c, d}]

{b, e}


It works also with more sets, lists or with any heads, e.g.:

Complement[{a, b, c, d, e}, {a}, {c, e}, {d}]

{b}


1. Sort order

It should be noted that Complement sorts its output:

la = {e, d, c, b, a};
lb = {a, b, c};

Complement[la, lb]


{d, e}

If we want to get the original sort order, we can use DeleteElements (new in 13.1)

DeleteElements[la, lb]


{e, d}

2. Duplicates

Complement deletes duplicates, DeleteElements doesn't

la = {e, e, d, d, c, b, a};
lb = {a, b, c};

Complement[la, lb]


{d, e}

DeleteElements[la, lb]


{e, e, d, d}

To delete duplicates when using DeleteElements:

DeleteDuplicates @ DeleteElements[la, lb]


{e, d}

Using DeleteCases and Union:

SetDifference[sets__?VectorQ,
Optional[opts : Automatic | "SortAndDistinct", Automatic]] :=
Module[
{setarray, sdiff, sdiffsorted},
setarray = {sets};
sdiff = DeleteCases[First @ setarray,
Apply[Alternatives, Union @@ Rest[setarray]]
];
sdiffsorted = Union @ sdiff;
Switch[
opts, Automatic,
sdiff, "SortAndDistinct",
sdiffsorted
]
];

l1 = {b, e, d, a, b, c, d}; l2 = {b, c}; l3 = {a, f};

SetDifference[l1, l2, l3]

(*{e, d, d}*)

SetDifference[l1, l2, l3, "SortAndDistinct"]

(*{d, e}*)

SetDifference[{a, b, b, d, e}, {c}, {c, e}, {d}]

(*{a, b, b}*)

SetDifference[{a, b, b, d, e}, {c}, {c, e}, {d}, "SortAndDistinct"]

(*{a, b}*)