Symmetric difference
From Rosetta Code
You are encouraged to solve this task according to the task description, using any language you may know.
Given two sets A and B, where A contains:
- John
- Bob
- Mary
- Serena
and B contains:
- Jim
- Mary
- John
- Bob
compute
That is, enumerate the items that are in A or B but not both. This set is called the symmetric difference of A and B.
Optionally, give the individual differences (
and
) as well.
Note: If your code uses lists of items to represent sets then ensure duplicate items in lists are correctly handled. For example two lists representing sets of a = ["John", "Serena", "Bob", "Mary", "Serena"] and b = ["Jim", "Mary", "John", "Jim", "Bob"] should produce the result of just two strings: ["Serena", "Jim"], in any order.
Contents |
[edit] Ada
Ada has the lattice operation xor predefined on Boolean, modular types, 1D arrays, set implementations from the standard library. The provided solution is uses arrays:
with Ada.Text_IO; use Ada.Text_IO;
procedure Test_XOR is
type Person is (John, Bob, Mary, Serena, Jim);
type Group is array (Person) of Boolean;
procedure Put (Set : Group) is
First : Boolean := True;
begin
for I in Set'Range loop
if Set (I) then
if First then
First := False;
else
Put (',');
end if;
Put (Person'Image (I));
end if;
end loop;
end Put;
A : Group := (John | Bob | Mary | Serena => True, others => False);
B : Group := (Jim | Mary | John | Bob => True, others => False);
begin
Put ("A xor B = "); Put (A xor B); New_Line;
Put ("A - B = "); Put (A and not B); New_Line;
Put ("B - A = "); Put (B and not A); New_Line;
end Test_XOR;
Sample output:
A xor B = SERENA,JIM A - B = SERENA B - A = JIM
[edit] AutoHotkey
setA = John, Bob, Mary, Serena
setB = Jim, Mary, John, Bob
MsgBox,, Singles, % SymmetricDifference(setA, setB)
setA = John, Serena, Bob, Mary, Serena
setB = Jim, Mary, John, Jim, Bob
MsgBox,, Duplicates, % SymmetricDifference(setA, setB)
;---------------------------------------------------------------------------
SymmetricDifference(A, B) { ; returns the symmetric difference of A and B
;---------------------------------------------------------------------------
StringSplit, A_, A, `,, %A_Space%
Loop, %A_0%
If Not InStr(B, A_%A_Index%)
And Not InStr(Result, A_%A_Index%)
Result .= A_%A_Index% ", "
StringSplit, B_, B, `,, %A_Space%
Loop, %B_0%
If Not InStr(A, B_%A_Index%)
And Not InStr(Result, B_%A_Index%)
Result .= B_%A_Index% ", "
Return, SubStr(Result, 1, -2)
}
Message boxes show:
Singles --------------------------- Serena, Jim OK
Duplicates --------------------------- Serena, Jim OK
[edit] C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const char mary[]="Mary";
const char bob[]="Bob";
const char jim[]="Jim";
const char john[]="John";
const char serena[]="Serena";
const char *setA[] = {john,bob,mary,serena};
const char *setB[] = {jim,mary,john,bob};
#define XSET(j) j, (sizeof(j)/sizeof(*j))
#define TALLOC(n,typ) malloc(n*sizeof(typ))
typedef enum {
esdDIFFERENCE,
esdSYMMETRIC } EsdFunction;
/** * * * * * * * * * * * * * * * * * * * *
* return value is difference or symmetric difference set
* its size is returned in sym_size
* f determinse whether it is a symmetric difference, or normal difference
* * * * * * * * * * * * * * * * * * * * **/
const char ** symmdiff( int *sym_size, EsdFunction f, const char *setA[], int setAsize, const char *setB[], int setBsize)
{
int union_size;
int max_union_size;
int diff_size;
const char **union_set;
const char **diff_set;
int *union_xor;
int ix, ixu;
max_union_size = setAsize + setBsize;
union_set = TALLOC(max_union_size, const char *);
union_xor = TALLOC(max_union_size, int);
/* I'm assuming here that setA has no duplicates,
* i.e. is a set in mathematical sense */
for (ix=0; ix<setAsize; ix++) {
union_set[ix] = setA[ix];
union_xor[ix] = 1;
}
diff_size = union_size = setAsize;
for (ix=0; ix<setBsize; ix++) {
for (ixu=0; ixu<union_size; ixu++) {
if (union_set[ixu] == setB[ix]) break;
}
if (ixu < union_size) { /* already in union */
union_xor[ixu] = 1-union_xor[ixu];
diff_size--;
}
else { /* not already in union -add */
if (f == esdSYMMETRIC) {
union_set[ixu] = setB[ix];
union_xor[ixu] = 1;
union_size++;
diff_size++;
}
}
}
/* Put results in symdiff set */
diff_set = TALLOC(diff_size, const char *);
ix = 0;
for (ixu=0; ixu<union_size; ixu++) {
if (union_xor[ixu]) {
if (ix == diff_size) {
printf("Short of space in diff_set\n");
exit(1);
}
diff_set[ix] = union_set[ixu];
ix++;
}
}
*sym_size = diff_size;
free(union_xor);
free(union_set);
return diff_set;
}
void printSet (const char *set[], int ssize)
{
int ix;
printf(" = {");
for (ix=0;ix<ssize; ix++) {
printf( "%s ", set[ix]);
}
printf("}\n");
}
int main()
{
const char **symset;
int sysize;
printf ("A symmdiff B");
symset = symmdiff( &sysize, esdSYMMETRIC, XSET(setA), XSET(setB));
printSet(symset, sysize);
free(symset);
printf ("A - B");
symset = symmdiff( &sysize, esdDIFFERENCE, XSET(setA), XSET(setB));
printSet(symset, sysize);
printf ("B - A");
symset = symmdiff( &sysize, esdDIFFERENCE, XSET(setB), XSET(setA));
printSet(symset, sysize);
free(symset);
return 0;
}
Output
A symmdiff B = {Serena Jim }
A - B = {Serena }
B - A = {Jim }
[edit] C++
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std ;
int main( ) {
string setA[ ] = { "John" , "Bob" , "Mary" , "Serena" } ;
string setB[ ] = { "Jim" , "Mary" , "John" , "Bob" } ;
set<string> firstSet ( setA , setA + 4 ) , secondSet( setB , setB + 4 ) , symdiff ;
set_symmetric_difference ( firstSet.begin( ) , firstSet.end( ) ,
secondSet.begin( ) , secondSet.end( ) ,
inserter( symdiff, symdiff.begin( ) ) ) ;
copy( symdiff.begin( ) , symdiff.end( ) , ostream_iterator<string>( cout , " " )) ;
cout << endl ;
return 0 ;
}
Output: Jim Serena
[edit] Clojure
(use '[clojure.set])
(defn symmetric-difference [s1 s2]
(union (difference s1 s2) (difference s2 s1)))
(symmetric-difference #{:john :bob :mary :serena} #{:jim :mary :john :bob})
[edit] Common Lisp
(defun symmetric-difference (l0 l1)
(union (set-difference l0 l1)
(set-difference l1 l0)))
(symmetric-difference '(John Bob Mary Serena) '(Jim Mary John Bob))
Output
(SERENA JIM)
[edit] D
Works with sets of any type (as long as they are of the same type)
import std.stdio;
import std.algorithm;
class Set(T) {
alias Set!(T) SetT;
T[] items;
this(T[] items) {
this.items = items;
}
SetT opSub(SetT other) {
T[] array;
foreach(a; items)
if(find(other.items, a).length == 0)
array ~= a;
return new SetT(array);
}
SetT opAdd(SetT other) {
return new SetT(this.items ~ (other - this).items);
}
}
T symDiff(T)(T left, T right) {
return (left - right) + (right - left);
}
void main()
{
auto A = new Set!(string)(["John", "Bob", "Mary", "Serena"]);
auto B = new Set!(string)(["Jim", "Mary", "John", "Bob"]);
writefln(" A/B: [%s]", (A - B).items);
writefln(" B/A: [%s]", (B - A).items);
writefln("A symdiff B: [%s]", (symDiff(A, B)).items);
}
Output:
A/B: [Serena]
B/A: [Jim]
A symdiff B: [Serena Jim]
[edit] Factor
: symmetric-diff ( a b -- c )
[ diff ] [ swap diff ] 2bi append ;
{ "John" "Bob" "Mary" "Serena" } { "Jim" "Mary" "John" "Bob" } symmetric-diff .
[edit] F#
> let a = Set.ofList ["John"; "Bob"; "Mary"; "Serena"]
let b = Set.ofList ["Jim"; "Mary"; "John"; "Bob"];;
val a : Set<string> = set ["Bob"; "John"; "Mary"; "Serena"]
val b : Set<string> = set ["Bob"; "Jim"; "John"; "Mary"]
> (a-b) + (b-a);;
val it : Set<string> = set ["Jim"; "Serena"]
Or, if you don't like the infix operators:
> Set.union (Set.difference a b) (Set.difference b a);;
val it : Set<string> = set ["Jim"; "Serena"]
[edit] Haskell
import Data.Set
a = fromList ["John", "Bob", "Mary", "Serena"]
b = fromList ["Jim", "Mary", "John", "Bob"]
(-|-) :: Ord a => Set a -> Set a -> Set a
(-|-) x y = (x \\ y) `union` (y \\ x)
-- Equivalently: (x `union` y) \\ (x `intersect` y)
Symmetric difference:
*Main> a -|- b
fromList ["Jim","Serena"]
Individual differences:
*Main> a \\ b
fromList ["Serena"]
*Main> b \\ a
fromList ["Jim"]
[edit] Icon and Unicon
[edit] Icon
Set operations are built into Icon/Unicon.
procedure main()Sample output:
a := set(["John", "Serena", "Bob", "Mary", "Serena"])
b := set(["Jim", "Mary", "John", "Jim", "Bob"])
showset("a",a)
showset("b",b)
showset("(a\\b) \xef (b\\a)",(a -- b) ++ (b -- a))
showset("(a\\b)",a -- b)
showset("(b\\a)",b -- a)
end
procedure showset(n,x)
writes(n," = { ")
every writes(!x," ")
write("}")
return
end
a = { Serena Mary Bob John }
b = { Mary Bob Jim John }
(a\b) ∩ (b\a) = { Serena Jim }
(a\b) = { Serena }
(b\a) = { Jim }
[edit] Unicon
This Icon solution works in Unicon.
[edit] J
A=: ;:'John Serena Bob Mary Serena'
B=: ;:'Jim Mary John Jim Bob'
(A-.B) ,&~. (B-.A) NB. Symmetric Difference
┌──────┬───┐
│Serena│Jim│
└──────┴───┘
A (-. ,&~. -.~) B NB. Tacit equivalent
┌──────┬───┐
│Serena│Jim│
└──────┴───┘
A -.&~. B NB. items in A but not in B
┌──────┐
│Serena│
└──────┘
B -.&~. A NB. items in B but not in A
┌───┐
│Jim│
└───┘
[edit] Java
import java.util.*;
public class SymmetricDifference {
/** Checks for elements in the first collection that aren't in the second collection.
We call this for each list, so we can get the symmetric difference. */
public static <E> Collection<E> inLeftNotRight(Collection<E> leftList, Collection<E> rightList) {
Collection<E> notFound = new ArrayList<E>(leftList);
notFound.removeAll(rightList);
return notFound;
}
public static void main(String[] args) {
Collection<String> listA = Arrays.asList("John", "Bob", "Mary", "Serena");
Collection<String> listB = Arrays.asList("Jim", "Mary", "John", "Bob");
// Present our initial data set
System.out.println("In list A: " + listA);
System.out.println("In list B: " + listB);
// Get our individual differences.
Collection<String> notInListA = inLeftNotRight(listB, listA);
Collection<String> notInListB = inLeftNotRight(listA, listB);
// The symmetric difference is the concatenation of the two individual differences
Collection<String> symmetricDifference = new ArrayList<String>(notInListA);
symmetricDifference.addAll(notInListB);
// Present our results
System.out.println("Not in list A: " + notInListA);
System.out.println("Not in list B: " + notInListB);
System.out.println("Symmetric Difference: " + symmetricDifference);
}
}
This outputs:
In list A: [John, Bob, Mary, Serena] In list B: [Jim, Mary, John, Bob] Not in list A: [Jim] Not in list B: [Serena] Symmetric Difference: [Jim, Serena]
[edit] JavaScript
Works with: JavaScript version 1.6 Works with: Firefox version 1.5
Works with: SpiderMonkey for the print() function.
Uses the Array function unique() defined here.
// in A but not in B
function relative_complement(A, B) {
return A.filter(function(elem) {return B.indexOf(elem) == -1});
}
// in A or in B but not in both
function symmetric_difference(A,B) {
return relative_complement(A,B).concat(relative_complement(B,A));
}
var a = ["John", "Serena", "Bob", "Mary", "Serena"].unique();
var b = ["Jim", "Mary", "John", "Jim", "Bob"].unique();
print(a);
print(b);
print(symmetric_difference(a,b));
outputs
Bob,John,Mary,Serena Bob,Jim,John,Mary Serena,Jim
[edit] Logo
Works with: UCB Logo
to diff :a :b [:acc []]
if empty? :a [output sentence :acc :b]
ifelse member? first :a :b ~
[output (diff butfirst :a remove first :a :b :acc)] ~
[output (diff butfirst :a :b lput first :a :acc)]
end
make "a [John Bob Mary Serena]
make "b [Jim Mary John Bob]
show diff :a :b ; [Serena Jim]
[edit] MATLAB
If you are using a vector of numbers as the sets of which you like to find the symmetric difference, then there are already utilities that operate on these types of sets built into MATLAB. This code will take the symmetric difference of two vectors:
>> [setdiff([1 2 3],[2 3 4]) setdiff([2 3 4],[1 2 3])]
ans =
1 4
On the other hand, if you are using cell-arrays as sets, there are no built-in set utilities to operate on those data structures, so you will have to program them yourself. Also, the only way to have a set of strings is to put each string in a cell of a cell array, trying to put them into a vector will cause all of the strings to concatenate.
This code will return the symmetric difference of two sets and will take both cell arrays and vectors (as in the above example) as inputs.
function resultantSet = symmetricDifference(set1,set2)
assert( ~xor(iscell(set1),iscell(set2)), 'Both sets must be of the same type, either cells or matricies, but not a combination of the two' );
%% Helper function definitions
%Define what set equality means for cell arrays
function trueFalse = equality(set1,set2)
if xor(iscell(set1),iscell(set2)) %set1 or set2 is a set and the other isn't
trueFalse = false;
return
elseif ~(iscell(set1) || iscell(set2)) %set1 and set2 are not sets
if ischar(set1) && ischar(set2) %set1 and set2 are chars or strings
trueFalse = strcmp(set1,set2);
elseif xor(ischar(set1),ischar(set2)) %set1 or set2 is a string but the other isn't
trueFalse = false;
else %set1 and set2 are not strings
if numel(set1) == numel(set2) %Since they must be matricies if the are of equal cardinality then they can be compaired
trueFalse = all((set1 == set2));
else %If they aren't of equal cardinality then they can't be equal
trueFalse = false;
end
end
return
else %set1 and set2 are both sets
for x = (1:numel(set1))
trueFalse = false;
for y = (1:numel(set2))
%Compair the current element of set1 with every element
%in set2
trueFalse = equality(set1{x},set2{y});
%If the element of set1 is equal to the current element
%of set2 remove that element from set2 and break out of
%this inner loop
if trueFalse
set2(y) = [];
break
end
end
%If the loop completes without breaking then the current
%element of set1 is not contained in set2 therefore the two
%sets are not equal and we can return an equality of false
if (~trueFalse)
return
end
end
%If, after checking every element in both sets, there are still
%elements in set2 then the two sets are not equivalent
if ~isempty(set2)
trueFalse = false;
end
%If the executation makes it here without the previous if
%statement evaluating to true, then this function will return
%true.
end
end %equality
%Define the relative compliment for cell arrays
function set1 = relativeComplement(set1,set2)
for k = (1:numel(set2))
if numel(set1) == 0
return
end
j = 1;
while j <= numel(set1)
if equality(set1{j},set2{k})
set1(j) = [];
j = j-1;
end
j = j+1;
end
end
end %relativeComplement
%% The Symmetric Difference Algorithm
if iscell(set1) && iscell(set2)
resultantSet = [relativeComplement(set1,set2) relativeComplement(set2,set1)];
else
resultantSet = [setdiff(set1,set2) setdiff(set2,set1)];
end
resultantSet = unique(resultantSet); %Make sure there are not duplicates
end %symmetricDifference
Solution Test:
>> A = {'John','Bob','Mary','Serena'}
A =
'John' 'Bob' 'Mary' 'Serena'
>> B = {'Jim','Mary','John','Bob'}
B =
'Jim' 'Mary' 'John' 'Bob'
>> symmetricDifference(A,B)
ans =
'Serena' 'Jim' %Correct
>> symmetricDifference([1 2 3],[2 3 4])
ans =
1 4 %Correct
[edit] OCaml
let ( -| ) a b =
List.filter (fun v -> not (List.mem v b)) a
let ( -|- ) a b = (b -| a) @ (a -| b)
in the toplevel:
# let a = [ "John"; "Bob"; "Mary"; "Serena" ]
and b = [ "Jim"; "Mary"; "John"; "Bob" ]
;;
val a : string list = ["John"; "Bob"; "Mary"; "Serena"]
val b : string list = ["Jim"; "Mary"; "John"; "Bob"]
# a -|- b ;;
- : string list = ["Jim"; "Serena"]
# a -| b ;;
- : string list = ["Serena"]
# b -| a ;;
- : string list = ["Jim"]
[edit] Oz
Oz does not have a general set data type. We can implement some basic set operations in terms of list functions and use them to define the symmetric difference:
declare
fun {SymDiff A B}
{Union {Diff A B} {Diff B A}}
end
%% implement sets in terms of lists
fun {MakeSet Xs}
set({Nub2 Xs nil})
end
fun {Diff set(A) set(B)}
set({FoldL B List.subtract A})
end
fun {Union set(A) set(B)}
set({Append A B})
end
%% --
fun {Nub2 Xs Ls}
case Xs of nil then nil
[] X|Xr andthen {Member X Ls} then {Nub2 Xr Ls}
[] X|Xr then X|{Nub2 Xr X|Ls}
end
end
in
{Show {SymDiff
{MakeSet [john bob mary serena]}
{MakeSet [jim mary john bob]}}}
{Show {SymDiff
{MakeSet [john serena bob mary serena]}
{MakeSet [jim mary john jim bob]}}}
Oz does have a type for finite sets of non-negative integers. This is part of the constraint programming support. For the given task, we could use it like this if we assume numbers instead of names:
declare
fun {SymDiff A B}
{FS.union {FS.diff A B} {FS.diff B A}}
end
A = {FS.value.make [1 2 3 4]}
B = {FS.value.make [5 3 1 2]}
in
{Show {SymDiff A B}}
[edit] Perl
my @a = qw(John Serena Bob Mary Serena);
my @b = qw(Jim Mary John Bob);
# Get the individual differences.
my @a_minus_b = setminus(\@a, \@b);
my @b_minus_a = setminus(\@b, \@a);
# merge then together and remove possible duplicates
my @symmetric_difference = uniq(@a_minus_b, @b_minus_a);
# Present our results.
print 'List A: ', join(', ', @a),
"\nList B: ", join(', ', @b),
"\nA \\ B: ", join(', ', @a_minus_b),
"\nB \\ A: ", join(', ', @b_minus_a),
"\nSymmetric difference: ", join(', ', @symmetric_difference), "\n";
# Takes two array references. Returns a list of elements in the first
# array that aren't in the second.
sub setminus
{
my ($a, $b) = @_;
# Convert $b to hash keys, so it's easier to search.
my %b;
@b{@$b} = ();
return grep !exists $b{$_}, @$a;
}
# take a list and return only uniq items
sub uniq
{
my %saw;
return grep !$saw{$_}++, @_;
}
This outputs:
List A: John, Serena, Bob, Mary, Serena List B: Jim, Mary, John, Bob A \ B: Serena, Serena B \ A: Jim Symmetric difference: Serena, Jim
[edit] Perl 6
my @firstnames = <John Serena Bob Mary Serena> ;
my @secondnames = <Jim Mary John Jim Bob> ;
my %infirstnames ;
my %insecondnames ;
for @firstnames -> $name {
%infirstnames{$name} = 0 ;
}
for @secondnames -> $name {
%insecondnames{$name} = 0 ;
}
my @symdifference ;
for %infirstnames.keys -> $name {
push @symdifference , $name unless ( %insecondnames.exists( $name ) ) ;
}
for %insecondnames.keys -> $name {
push @symdifference , $name unless ( %infirstnames.exists( $name ) ) ;
}
say @symdifference.join( ", " ) ;
This produces the output:
Serena, Jim
[edit] PHP
<?php
$a = array('John', 'Bob', 'Mary', 'Serena');
$b = array('Jim', 'Mary', 'John', 'Bob');
// Remove any duplicates
$a = array_unique($a);
$b = array_unique($b);
// Get the individual differences, using array_diff()
$a_minus_b = array_diff($a, $b);
$b_minus_a = array_diff($b, $a);
// Simply merge them together to get the symmetric difference
$symmetric_difference = array_merge($a_minus_b, $b_minus_a);
// Present our results.
echo 'List A: ', implode(', ', $a),
"\nList B: ", implode(', ', $b),
"\nA \\ B: ", implode(', ', $a_minus_b),
"\nB \\ A: ", implode(', ', $b_minus_a),
"\nSymmetric difference: ", implode(', ', $symmetric_difference), "\n";
?>
This outputs:
List A: John, Bob, Mary, Serena List B: Jim, Mary, John, Bob A \ B: Serena B \ A: Jim Symmetric difference: Serena, Jim
[edit] PicoLisp
(de symdiff (A B)
(uniq (conc (diff A B) (diff B A))) )
Output:
(symdiff '(John Serena Bob Mary Serena) '(Jim Mary John Jim Bob)) -> (Serena Jim)
[edit] PureBasic
[edit] Simple approach
Dim A.s(3)
Dim B.s(3)
A(0)="John": A(1)="Bob": A(2)="Mary": A(3)="Serena"
B(0)="Jim": B(1)="Mary":B(2)="John": B(3)="Bob"
For a=0 To ArraySize(A()) ; A-B
For b=0 To ArraySize(B())
If A(a)=B(b)
Break
ElseIf b=ArraySize(B())
Debug A(a)
EndIf
Next b
Next a
For b=0 To ArraySize(B()) ; B-A
For a=0 To ArraySize(A())
If A(a)=B(b)
Break
ElseIf a=ArraySize(A())
Debug B(b)
EndIf
Next a
Next b
[edit] Solution using lists
DataSection
SetA:
Data.i 4
Data.s "John", "Bob", "Mary", "Serena"
; Data.i 5
; Data.s "John", "Serena", "Bob", "Mary", "Serena"
SetB:
Data.i 4
Data.s "Jim", "Mary", "John", "Bob"
; Data.i 5
; Data.s "Jim", "Mary", "John", "Jim", "Bob"
EndDataSection
Procedure addElementsToSet(List x.s())
;requires the read pointer to be set prior to calling by using 'Restore'
Protected i, count
Read.i count
For i = 1 To count
AddElement(x())
Read.s x()
Next
EndProcedure
Procedure displaySet(List x.s())
Protected i, count = ListSize(x())
FirstElement(x())
For i = 1 To count
Print(x())
NextElement(x())
If i <> count: Print(", "): EndIf
Next
PrintN("")
EndProcedure
Procedure symmetricDifference(List a.s(), List b.s(), List result.s())
Protected ACount = ListSize(a()), BCount = ListSize(b()), prev.s
;this may leave set a and b in a different order
SortList(a(),#PB_Sort_Ascending)
SortList(b(),#PB_Sort_Ascending)
FirstElement(a())
FirstElement(b())
LastElement(result()) ;add to end of result()
While ACount > 0 Or BCount > 0
If ACount <> 0 And BCount <> 0 And a() = b()
ACount - 1: NextElement(a())
BCount - 1: NextElement(b())
ElseIf BCount = 0 Or (ACount <> 0 And a() < b())
AddElement(result()): result() = a()
prev = a(): Repeat: ACount - 1: NextElement(a()): Until ACount = 0 Or (a() <> prev)
ElseIf ACount = 0 Or (BCount <> 0 And a() > b())
AddElement(result()): result() = b()
prev = b(): Repeat: BCount - 1: NextElement(b()): Until BCount = 0 Or (b() <> prev)
EndIf
Wend
EndProcedure
If OpenConsole()
NewList a.s(): Restore SetA: addElementsToSet(a())
NewList b.s(): Restore SetB: addElementsToSet(b())
Print("Set A: "): displaySet(a())
Print("Set B: "): displaySet(b())
NewList sd.s()
symmetricDifference(a(), b(), sd())
Print("Symmetric Difference: "): displaySet(sd())
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf
Sample output:
Set A: John, Bob, Mary, Serena Set B: Jim, Mary, John, Bob Symmetric Difference: Jim, Serena
[edit] Python
Python's set type supports difference as well as symmetric difference operators
>>> setA = set(["John", "Bob", "Mary", "Serena"])
>>> setB = set(["Jim", "Mary", "John", "Bob"])
>>> setA ^ setB # symmetric difference of A and B
set(['Jim', 'Serena'])
>>> setA - setB # elements in A that are not in B
set(['Serena'])
>>> setB - setA # elements in B that are not in A
set(['Jim'])
[edit] R
a <- c( "John", "Bob", "Mary", "Serena" )
b <- c( "Jim", "Mary", "John", "Bob" )
c(setdiff(b, a), setdiff(a, b))
a <- c("John", "Serena", "Bob", "Mary", "Serena")
b <- c("Jim", "Mary", "John", "Jim", "Bob")
c(setdiff(b, a), setdiff(a, b))
In both cases answer is:
[1] "Jim" "Serena"
[edit] Ruby
First, handle possible non-unique elements
# with sets
require 'set'
a = Set["John", "Serena", "Bob", "Mary", "Serena"]
b = Set["Jim", "Mary", "John", "Jim", "Bob"]
# or, with arrays
a = ["John", "Serena", "Bob", "Mary", "Serena"]
b = ["Jim", "Mary", "John", "Jim", "Bob"]
a.uniq!
b.uniq!
Then, find the differences. Both Set and Array objects understand these operations:
a_not_b = a - b
b_not_a = b - a
sym_diff = a_not_b + b_not_a
[edit] Scala
import scala.collection.mutable.Set
import scala.collection.mutable.HashSet
val s1 = HashSet("John", "Serena", "Bob", "Mary", "Serena")
val s2 = HashSet("Jim", "Mary", "John", "Jim", "Bob")
def complement(fst: Set[String], snd: Set[String]) =
fst.filter{ el => !snd.contains(el) }.toList
def symdiff(fst: Set[String], snd: Set[String]) =
HashSet(complement(fst, snd) ++ complement(snd, fst):_*)
println(s1)
println(s2)
println(symdiff(s1, s2))
Output is
Set(John, Serena, Mary, Bob) Set(John, Mary, Jim, Bob) Set(Serena, Jim)
[edit] Smalltalk
|A B|
A := Set new.
B := Set new.
A addAll: #( 'John' 'Bob' 'Mary' 'Serena' ).
B addAll: #( 'Jim' 'Mary' 'John' 'Bob' ).
( (A - B) + (B - A) ) displayNl.
Output is
Set ('Jim' 'Serena' )
[edit] Tcl
It's common to represent sets as an unordered list of elements. (It is also the most efficient representation.) The struct::set package contains operations for working on such sets-as-lists.
Library: tcllib
package require struct::setProduces this output:
set A {John Bob Mary Serena}
set B {Jim Mary John Bob}
set AnotB [struct::set difference $A $B]
set BnotA [struct::set difference $B $A]
set SymDiff [struct::set union $AnotB $BnotA]
puts "A\\B = $AnotB"
puts "B\\A = $BnotA"
puts "A\u2296B = $SymDiff"
# Of course, the library already has this operation directly...
puts "Direct Check: [struct::set symdiff $A $B]"
A\B = Serena B\A = Jim A⊖B = Jim Serena Direct Check: Jim Serena
[edit] Ursala
a = <'John','Bob','Mary','Serena'>
b = <'Jim','Mary','John','Bob'>
#cast %sLm
main =
<
'a': a,
'b': b,
'a not b': ~&j/a b,
'b not a': ~&j/b a,
'symmetric difference': ~&jrljTs/a b>
output:
< 'a': <'John','Bob','Mary','Serena'>, 'b': <'Jim','Mary','John','Bob'>, 'a not b': <'Serena'>, 'b not a': <'Jim'>, 'symmetric difference': <'Jim','Serena'>>

