4

I have two lists: excluded and values. I would like to efficiently determine whether excluded and values are disjoint. How does one go about doing this (preferably using FreeQ)?

pre-kidney
  • 693
  • 3
  • 9

5 Answers5

13

In version 10.0 you have DisjointQ (and conversely IntersectingQ) to test this. 10.2 adds the Contains* family of function with ContainsNone being equivalent to DisjointQ. For earlier versions you could build this yourself:

ClearAll[disjointQ]
disjointQ[a_List, b_List] := Intersection[a, b] === {}

disjointQ[{1, 2, 3}, {6, 4, 5}]
(* True *)

disjointQ[{1, 2, 3}, {1, 4, 5}]
(* False *)
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
4

I'd expect this might be faster than intersection on larger lists:

With[{j = Join[DeleteDuplicates@#1, DeleteDuplicates@#2]}, DeleteDuplicates@j == j] &[l1, l2]

Addendum - a little testing, does seem to have advantage when both lists large, otherwise a bit of a wash between this and using intersection... perhaps others can test on non-loungbook environments - I get wildly varying results depending on how I produce the random test lists :-|

Addendum 2: Per comments, differences were from packed/unpacked lists, and in my limited tests the above is faster for unpacked... carry on...

ciao
  • 25,774
  • 2
  • 58
  • 139
4

While highly inefficient you asked about FreeQ and you could do this:

f0 = FreeQ[#, Alternatives @@ #2] &;

More practically here is a condensed version of rasher/ciao's method:

f1 = DuplicateFreeQ[Join @@ DeleteDuplicates /@ {##}] &
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
1

For short lists (see comment of Domen) we could use DeleteElements or UniqueElements

1.

DeleteElements (new in 13.1)

a = {1, 2, 3};
b = {6, 4, 5};

DeleteElements[a, b] == a

True

a = {1, 2, 3};
b = {6, 1, 5};

DeleteElements[a, b] == a

False

2.

With UniqueElements (also new in 13.1) we can test more than 2 lists

a = {1, 2, 3};
b = {6, 4, 5};
c = {9, 8, 7};

UniqueElements[{a, b, c}] == {a, b, c}

True

a = {1, 2, 3};
b = {6, 4, 5};
c = {9, 2, 7};

UniqueElements[{a, b, c}] == {a, b, c}

False

eldo
  • 67,911
  • 5
  • 60
  • 168
1

Following @eldo's good observation about UniqueElements and grabbing his examples, we can use Tally and MatchQ as follows:

disjointQ[l__List] := MatchQ[Tally[Join[l]][[All, 2]], {1 ..}]

disjointQ[{1, 2, 3}, {6, 4, 5}]

(True)

disjointQ[{1, 2, 3}, {1, 4, 5}]

(False)

a1 = {1, 2, 3}; b1 = {6, 4, 5}; c1 = {9, 8, 7};

disjointQ[a1, b1, c1]

(True)

a2 = {1, 2, 3}; b2 = {6, 4, 5}; c2 = {9, 2, 7};

disjointQ[a2, b2, c2]

(False)

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44