5
$\begingroup$

By "opposite of intersection" I mean that if I have two lists like so:

list1 = {1,2,4,7,9}; list2 = {1,4,9,10,11}

And then we do the "Reverse Intersection" on these two lists of integers to output:

ReverseIntersection[list1, list2] = {2,7,10,11}

Thanks!

$\endgroup$
  • 2
    $\begingroup$ This is called the symmetric difference. It seems that there is no built-in in WL, but it is easily implemented. $\endgroup$ – Stephen Powell Apr 14 '18 at 7:57
  • $\begingroup$ Duplicate. $\endgroup$ – Alan Apr 14 '18 at 15:58
9
$\begingroup$

There is probably a build-in command for this, but with over 6,000 commands, hard to search now. But you could try

inter=Intersection[list1,list2];
Complement[Union[list1,list2],inter]

Mathematica graphics

$\endgroup$
  • $\begingroup$ Yes, the OP wants the elements of the union that are not in the intersection...(+1) $\endgroup$ – José Antonio Díaz Navas Apr 14 '18 at 19:26
2
$\begingroup$

A Small Code for Arbitrary Number of Sets

As @Nasser pointed out, the simplest answer is

inter=Intersection[list1,list2];
Complement[Union[list1,list2],inter]

However, one can generalize the situation to an arbitrary number of lists. For that, I wrote the following small code:

selector[lists_, selection_] := Module[{mid}, 
    mid = Pick[lists,selection, 1]; 
    Complement[
         If[Length[mid] == 1, Flatten[mid], Intersection @@ mid], ##
    ]&[Sequence @@ Pick[lists, selection, 0]]
];

which basically gives any conbination of intersection and complement for arbitrary number of sets.

It works as follows: One combines all sets into a matrix of the form $\{list1, list2, list3, \dots, listN\}$. Then, selector[$\{list1, list2, list3, \dots, listN\}$,$\{i1,i2,i3,\dots,iN\}$] gives the set whose elements are in the sets for which $i=1$ AND not in the sets for which $i=0$.

For example, let us consider \begin{align} lis1=&\{a, b, c\}\\list2=&\{b, c, d\}\\ list3=&\{c, e\} \end{align} and define

lists = {{a, b, c}, {b, c, d}, {c, e}};

We see that

selector[lists, {1, 1, 1}]

{c}

which indicates $c$ is the element of all lists. Likewise

selector[lists, {1, 1, 0}]

{b}

indicating that $b$ is the only element present in both first and second list and not present in third list.

We can generate all such possibilities with Tuples:

Tuples[{0, 1}, 3]

{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}}

First one is the empty set; if we consider selector for rest of the possibilities, we get:

selector[lists, #] & /@ Rest[Tuples[{0, 1}, 3]]

{{e}, {d}, {}, {a}, {}, {b}, {c}}

We see that we get each and every term only once: selector creates the mutually exclusive cases as expected. The union of these give the universal set.

Question at Hand

We can find distinct sets for the case of original question as we did above:

selector[{{1, 2, 4, 7, 9}, {1, 4, 9, 10, 11}}, #] & /@ Rest[Tuples[{0, 1}, 2]]

{{10, 11}, {2, 7}, {1, 4, 9}}

As we are interested in the union of exclusive complements, we want the union of the cases $\{1,0\}$ and $\{0,1\}$, hence

selector[{{1, 2, 4, 7, 9}, {1, 4, 9, 10, 11}}, #] & /@ {{1, 0}, {0,1}} // Flatten

{2, 7, 10, 11}

Of course, for this question, this method is just an overkill!

A More Complicated Example

As an example, let us consider the following:

mul2 = Table[2 i, {i, 25}];
mul3 = Table[3 i, {i, 16}];
mul4 = Table[4 i, {i, 12}];
mul5 = Table[5 i, {i, 10}];
mul6 = Table[6 i, {i, 8}];
selector[{mul2, mul3, mul4, mul5, mul6}, #] & /@ Rest[Tuples[{0, 1}, 5]]

where $mul2$ are multiples of $2$ below 50, $mul3$ are multiples of $3$ below 50, and so forth. When we run this, we get

{{}, {5, 25, 35}, {}, {}, {}, {}, {}, {3, 9, 21, 27, 33, 39}, {}, {15, 45}, {}, {}, {}, {}, {}, {2, 14, 22, 26, 34, 38, 46}, {}, {10, 50}, {}, {4, 8, 16, 28, 32, 44}, {}, {20, 40}, {}, {}, {6, 18, 42}, {}, {30}, {}, {12, 24, 36, 48}, {}, {}}

which gives us the partitions of numbers below 50 with respect to their divisibility for $2,3,4,5,6$.

$\endgroup$
1
$\begingroup$

Exploiting the commutativity of the symmetric difference, Nasser's answer can be generalized to more than two sets by this:

symmetricDifference[list1_List, list2_List] := 
  Complement[Union[list1, list2], Intersection[list1, list2]];

symmetricDifference[a___List, list1_List, list2_List, b___List] := 
  symmetricDifference[a, symmetricDifference[list1, list2], b];

A second generalization can be obtained by observing that the symmetric difference of several lists contains only those elements that appear only an odd number of times in the lists. We can use Tally for counting like this:

symmetricDifference2[lists__List] := 
 Pick[#1, OddQ[#2]] & @@ Transpose[Tally[Sort[Join[lists]]]]

A quick comparison of these two methods:

m = 1000;
n = 500;
lists = Table[RandomSample[Range[1, m], n], {20}];

a = symmetricDifference @@ lists; // RepeatedTiming // First
b = symmetricDifference2 @@ lists; // RepeatedTiming // First

a == b

0.0015

0.000671

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.