Symmetric difference: Difference between revisions
(Added Algol 68) |
m (First example shows symmetric difference w/o using `><` operator) |
||
(40 intermediate revisions by 27 users not shown) | |||
Line 20: | Line 20: | ||
# In the mathematical notation above <code>A \ B</code> gives the set of items in A that are not in B; <code>A ∪ B</code> gives the set of items in both A and B, (their ''union''); and <code>A ∩ B</code> gives the set of items that are in both A and B (their ''intersection''). |
# In the mathematical notation above <code>A \ B</code> gives the set of items in A that are not in B; <code>A ∪ B</code> gives the set of items in both A and B, (their ''union''); and <code>A ∩ B</code> gives the set of items that are in both A and B (their ''intersection''). |
||
<br><br> |
<br><br> |
||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">V setA = Set([‘John’, ‘Bob’, ‘Mary’, ‘Serena’]) |
|||
V setB = Set([‘Jim’, ‘Mary’, ‘John’, ‘Bob’]) |
|||
print(setA.symmetric_difference(setB)) |
|||
print(setA - setB) |
|||
print(setB - setA)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Set([Jim, Serena]) |
|||
Set([Serena]) |
|||
Set([Jim]) |
|||
</pre> |
|||
=={{header|Action!}}== |
|||
The user must type in the monitor the following command after compilation and before running the program!<pre>SET EndProg=*</pre> |
|||
{{libheader|Action! Tool Kit}} |
|||
<syntaxhighlight lang="action!">CARD EndProg ;required for ALLOCATE.ACT |
|||
INCLUDE "D2:ALLOCATE.ACT" ;from the Action! Tool Kit. You must type 'SET EndProg=*' from the monitor after compiling, but before running this program! |
|||
DEFINE PTR="CARD" |
|||
DEFINE NODE_SIZE="6" |
|||
TYPE SetNode=[PTR data,prv,nxt] |
|||
TYPE SetInfo=[PTR name,begin,end] |
|||
PROC PrintSet(SetInfo POINTER s) |
|||
SetNode POINTER n |
|||
CHAR ARRAY a |
|||
n=s.begin |
|||
PrintF("%S=(",s.name) |
|||
WHILE n |
|||
DO |
|||
Print(n.data) |
|||
a=n.data |
|||
IF n.nxt THEN |
|||
Print(", ") |
|||
FI |
|||
n=n.nxt |
|||
OD |
|||
PrintE(")") |
|||
RETURN |
|||
PROC CreateSet(SetInfo POINTER s CHAR ARRAY n) |
|||
s.name=n |
|||
s.begin=0 |
|||
s.end=0 |
|||
RETURN |
|||
PTR FUNC Find(SetInfo POINTER s CHAR ARRAY v) |
|||
SetNode POINTER n |
|||
n=s.begin |
|||
WHILE n |
|||
DO |
|||
IF SCompare(v,n.data)=0 THEN |
|||
RETURN (n) |
|||
FI |
|||
n=n.nxt |
|||
OD |
|||
RETURN (0) |
|||
BYTE FUNC Contains(SetInfo POINTER s CHAR ARRAY v) |
|||
SetNode POINTER n |
|||
n=Find(s,v) |
|||
IF n=0 THEN |
|||
RETURN (0) |
|||
FI |
|||
RETURN (1) |
|||
PROC Append(SetInfo POINTER s CHAR ARRAY v) |
|||
SetNode POINTER n,tmp |
|||
IF Contains(s,v) THEN RETURN FI |
|||
n=Alloc(NODE_SIZE) |
|||
n.data=v |
|||
n.prv=s.end |
|||
n.nxt=0 |
|||
IF s.end THEN |
|||
tmp=s.end tmp.nxt=n |
|||
ELSE |
|||
s.begin=n |
|||
FI |
|||
s.end=n |
|||
RETURN |
|||
PROC Remove(SetInfo POINTER s CHAR ARRAY v) |
|||
SetNode POINTER n,prev,next |
|||
n=Find(s,v) |
|||
IF n=0 THEN RETURN FI |
|||
prev=n.prv |
|||
next=n.nxt |
|||
Free(n,NODE_SIZE) |
|||
IF prev THEN |
|||
prev.nxt=next |
|||
ELSE |
|||
s.begin=next |
|||
FI |
|||
IF next THEN |
|||
next.prv=prev |
|||
ELSE |
|||
s.end=prev |
|||
FI |
|||
RETURN |
|||
PROC AppendSet(SetInfo POINTER s,other) |
|||
SetNode POINTER n |
|||
n=other.begin |
|||
WHILE n |
|||
DO |
|||
Append(s,n.data) |
|||
n=n.nxt |
|||
OD |
|||
RETURN |
|||
PROC RemoveSet(SetInfo POINTER s,other) |
|||
SetNode POINTER n |
|||
n=other.begin |
|||
WHILE n |
|||
DO |
|||
Remove(s,n.data) |
|||
n=n.nxt |
|||
OD |
|||
RETURN |
|||
PROC Clear(SetInfo POINTER s) |
|||
SetNode POINTER n |
|||
DO |
|||
n=s.begin |
|||
IF n=0 THEN RETURN FI |
|||
Remove(s,n.data) |
|||
OD |
|||
RETURN |
|||
PROC Union(SetInfo POINTER a,b,res) |
|||
Clear(res) |
|||
AppendSet(res,a) |
|||
AppendSet(res,b) |
|||
RETURN |
|||
PROC Difference(SetInfo POINTER a,b,res) |
|||
Clear(res) |
|||
AppendSet(res,a) |
|||
RemoveSet(res,b) |
|||
RETURN |
|||
PROC SymmetricDifference(SetInfo POINTER a,b,res) |
|||
SetInfo tmp1,tmp2 |
|||
CreateSet(tmp1,"") |
|||
CreateSet(tmp2,"") |
|||
Difference(a,b,tmp1) |
|||
Difference(b,a,tmp2) |
|||
Union(tmp1,tmp2,res) |
|||
Clear(tmp1) |
|||
Clear(tmp2) |
|||
RETURN |
|||
PROC TestSymmetricDifference(SetInfo POINTER a,b,res) |
|||
SymmetricDifference(a,b,res) |
|||
PrintF("%S XOR %S: ",a.name,b.name) |
|||
PrintSet(res) |
|||
RETURN |
|||
PROC TestDifference(SetInfo POINTER a,b,res) |
|||
Difference(a,b,res) |
|||
PrintF("%S-%S: ",a.name,b.name) |
|||
PrintSet(res) |
|||
RETURN |
|||
PROC Main() |
|||
SetInfo s1,s2,s3 |
|||
Put(125) PutE() ;clear screen |
|||
AllocInit(0) |
|||
CreateSet(s1,"A") |
|||
CreateSet(s2,"B") |
|||
CreateSet(s3,"C") |
|||
Append(s1,"John") Append(s1,"Bob") |
|||
Append(s1,"Mary") Append(s1,"Serena") |
|||
Append(s2,"Jim") Append(s2,"Mary") |
|||
Append(s2,"John") Append(s2,"Bob") |
|||
PrintSet(s1) PrintSet(s2) |
|||
PutE() |
|||
TestSymmetricDifference(s1,s2,s3) |
|||
TestDifference(s1,s2,s3) |
|||
TestDifference(s2,s1,s3) |
|||
Clear(s1) |
|||
Clear(s2) |
|||
Clear(s3) |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Symmetric_difference.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
A=(John, Bob, Mary, Serena) |
|||
B=(Jim, Mary, John, Bob) |
|||
A XOR B: C=(Serena, Jim) |
|||
A-B: C=(Serena) |
|||
B-A: C=(Jim) |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
Ada has the lattice operation '''xor''' predefined on Boolean, modular types, 1D arrays, set implementations from the standard library. The provided solution uses arrays: |
Ada has the lattice operation '''xor''' predefined on Boolean, modular types, 1D arrays, set implementations from the standard library. The provided solution uses arrays: |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO; |
||
procedure Test_XOR is |
procedure Test_XOR is |
||
Line 49: | Line 268: | ||
Put ("A - B = "); Put (A and not B); New_Line; |
Put ("A - B = "); Put (A and not B); New_Line; |
||
Put ("B - A = "); Put (B and not A); New_Line; |
Put ("B - A = "); Put (B and not A); New_Line; |
||
end Test_XOR;</ |
end Test_XOR;</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre> |
<pre> |
||
Line 58: | Line 277: | ||
=={{header|Aime}}== |
=={{header|Aime}}== |
||
< |
<syntaxhighlight lang="aime">show_sdiff(record u, x) |
||
{ |
{ |
||
record r; |
record r; |
||
Line 91: | Line 310: | ||
0; |
0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Jim |
<pre>Jim |
||
Line 99: | Line 318: | ||
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}} |
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}} |
||
Uses the associative array implementations in ALGOL_68/prelude. |
Uses the associative array implementations in ALGOL_68/prelude. |
||
< |
<syntaxhighlight lang="algol68"># symetric difference using associative arrays to represent the sets # |
||
# include the associative array code for string keys and values # |
# include the associative array code for string keys and values # |
||
PR read "aArray.a68" PR |
PR read "aArray.a68" PR |
||
Line 154: | Line 373: | ||
e := NEXT c |
e := NEXT c |
||
OD; |
OD; |
||
print( ( newline ) )</ |
print( ( newline ) )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Serena Jim |
Serena Jim |
||
</pre> |
|||
=={{header|Amazing Hopper}}== |
|||
<syntaxhighlight lang="c"> |
|||
#include <basico.h> |
|||
algoritmo |
|||
matrices (A, B) |
|||
"John", "Bob", "Mary", "Serena", enlistar en 'A' |
|||
"Jim", "Mary", "John", "Bob", enlistar en 'B' |
|||
" A XOR B: {", diferencia simétrica(A,B), "}\n" |
|||
" A \ B: {", diferencia(A,B), "}\n" |
|||
" B \ A: {", diferencia(B,A), "}\n" |
|||
imprimir |
|||
terminar |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A XOR B: {Jim,Serena} |
|||
A \ B: {Serena} |
|||
B \ A: {Jim} |
|||
</pre> |
</pre> |
||
=={{header|Apex}}== |
=={{header|Apex}}== |
||
< |
<syntaxhighlight lang="java">Set<String> setA = new Set<String>{'John', 'Bob', 'Mary', 'Serena'}; |
||
Set<String> setB = new Set<String>{'Jim', 'Mary', 'John', 'Bob'}; |
Set<String> setB = new Set<String>{'Jim', 'Mary', 'John', 'Bob'}; |
||
Line 188: | Line 431: | ||
System.debug('Not in set B: ' + notInSetB); |
System.debug('Not in set B: ' + notInSetB); |
||
System.debug('Symmetric Difference: ' + symmetricDifference); |
System.debug('Symmetric Difference: ' + symmetricDifference); |
||
System.debug('Symmetric Difference 2: ' + symmetricDifference2);</ |
System.debug('Symmetric Difference 2: ' + symmetricDifference2);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Not in set A: {Jim} |
<pre>Not in set A: {Jim} |
||
Line 194: | Line 437: | ||
Symmetric Difference: {Jim, Serena} |
Symmetric Difference: {Jim, Serena} |
||
Symmetric Difference 2: {Jim, Serena}</pre> |
Symmetric Difference 2: {Jim, Serena}</pre> |
||
=={{header|APL}}== |
|||
{{works with|Dyalog APL}} |
|||
<syntaxhighlight lang="apl">symdiff ← ∪~∩</syntaxhighlight> |
|||
{{out}} |
|||
<pre> 'John' 'Bob' 'Mary' 'Serena' symdiff 'Jim' 'Mary' 'John' 'Bob' |
|||
Serena Jim </pre> |
|||
=={{header|AppleScript}}== |
=={{header|AppleScript}}== |
||
===Functional=== |
|||
{{Trans|JavaScript}} (ES6 Functional JS) |
{{Trans|JavaScript}} (ES6 Functional JS) |
||
< |
<syntaxhighlight lang="applescript">-- SYMMETRIC DIFFERENCE ------------------------------------------- |
||
-- symmetricDifference :: [a] -> [a] -> [a] |
-- symmetricDifference :: [a] -> [a] -> [a] |
||
Line 308: | Line 559: | ||
set sx to nub(xs) |
set sx to nub(xs) |
||
sx & foldl(flipDelete, nub(ys), sx) |
sx & foldl(flipDelete, nub(ys), sx) |
||
end union</ |
end union</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
< |
<syntaxhighlight lang="applescript">{"Serena", "Jim"}</syntaxhighlight> |
||
===Some alternatives=== |
|||
There are several ways to approach this problem. Vanilla AppleScript doesn't do sets, but the following returns the required results: |
|||
<syntaxhighlight lang="applescript">on symmetricDifference(a, b) |
|||
set output to {} |
|||
repeat 2 times |
|||
repeat with thisItem in a |
|||
set thisItem to thisItem's contents |
|||
tell {thisItem} |
|||
if (not ((it is in b) or (it is in output))) then set end of output to thisItem |
|||
end tell |
|||
end repeat |
|||
set {a, b} to {b, a} |
|||
end repeat |
|||
return output |
|||
end symmetricDifference |
|||
on task() |
|||
=={{header|Arturo}}== |
|||
set a to {"John", "Serena", "Bob", "Mary", "Serena"} |
|||
set b to {"Jim", "Mary", "John", "Jim", "Bob"} |
|||
return symmetricDifference(a, b) |
|||
end task |
|||
task()</syntaxhighlight> |
|||
<lang arturo>A: #(@John @Bob @Mary @Serena) |
|||
B: #(@Jim @Mary @John @Bob) |
|||
{{output}} |
|||
print [symmetricDifference A B]</lang> |
|||
<syntaxhighlight lang="applescript">{"Serena", "Jim"}</syntaxhighlight> |
|||
AppleScriptObjC gives access to the Foundation framework's NSSet classes, whose mutable variety has relevant methods. A symmetricDifference() handler implementing (A ∖ B) ∪ (B ∖ A) might be: |
|||
<syntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later |
|||
use framework "Foundation" |
|||
on symmetricDifference(a, b) |
|||
set a to current application's class "NSSet"'s setWithArray:(a) |
|||
set b to current application's class "NSMutableSet"'s setWithArray:(b) |
|||
set output to a's mutableCopy() |
|||
tell output to minusSet:(b) |
|||
tell b to minusSet:(a) |
|||
tell output to unionSet:(b) |
|||
return output's allObjects() as list |
|||
end symmetricDifference</syntaxhighlight> |
|||
And for (A ∪ B) ∖ (A ∩ B): |
|||
<syntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later |
|||
use framework "Foundation" |
|||
on symmetricDifference(a, b) |
|||
set a to current application's class "NSSet"'s setWithArray:(a) |
|||
set b to current application's class "NSMutableSet"'s setWithArray:(b) |
|||
set output to a's mutableCopy() |
|||
tell output to unionSet:(b) |
|||
tell b to intersectSet:(a) |
|||
tell output to minusSet:(b) |
|||
return output's allObjects() as list |
|||
end symmetricDifference</syntaxhighlight> |
|||
It's also possible in ASObjC to filter arrays or sets if you're so inclined: |
|||
<syntaxhighlight lang="applescript">use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later |
|||
use framework "Foundation" |
|||
on symmetricDifference(a, b) |
|||
set unionArray to (current application's class "NSArray"'s arrayWithArray:({a, b}))'s ¬ |
|||
valueForKeyPath:("@distinctUnionOfArrays.self") |
|||
set filter to current application's class "NSPredicate"'s ¬ |
|||
predicateWithFormat_("!((self IN %@) && (self IN %@))", a, b) |
|||
return (unionArray's filteredArrayUsingPredicate:(filter)) as list |
|||
end symmetricDifference</syntaxhighlight> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">a: ["John" "Bob" "Mary" "Serena"] |
|||
b: ["Jim" "Mary" "John" "Bob"] |
|||
print difference.symmetric a b</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre>Serena Jim</pre> |
||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">setA = John, Bob, Mary, Serena |
||
setB = Jim, Mary, John, Bob |
setB = Jim, Mary, John, Bob |
||
MsgBox,, Singles, % SymmetricDifference(setA, setB) |
MsgBox,, Singles, % SymmetricDifference(setA, setB) |
||
Line 346: | Line 671: | ||
Result .= B_%A_Index% ", " |
Result .= B_%A_Index% ", " |
||
Return, SubStr(Result, 1, -2) |
Return, SubStr(Result, 1, -2) |
||
}</ |
}</syntaxhighlight> |
||
Message boxes show: |
Message boxes show: |
||
<pre>Singles |
<pre>Singles |
||
Line 360: | Line 685: | ||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f SYMMETRIC_DIFFERENCE.AWK |
# syntax: GAWK -f SYMMETRIC_DIFFERENCE.AWK |
||
BEGIN { |
BEGIN { |
||
Line 392: | Line 717: | ||
printf("\n") |
printf("\n") |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
<p>output:</p> |
<p>output:</p> |
||
<pre> |
<pre> |
||
Line 402: | Line 727: | ||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
Here sets are represented as integers, hence there are a maximum of 32 elements in a set. |
Here sets are represented as integers, hence there are a maximum of 32 elements in a set. |
||
< |
<syntaxhighlight lang="bbcbasic"> DIM list$(4) |
||
list$() = "Bob", "Jim", "John", "Mary", "Serena" |
list$() = "Bob", "Jim", "John", "Mary", "Serena" |
||
Line 424: | Line 749: | ||
IF set% AND 1 << i% o$ += list$(i%) + ", " |
IF set% AND 1 << i% o$ += list$(i%) + ", " |
||
NEXT |
NEXT |
||
= LEFT$(LEFT$(o$))</ |
= LEFT$(LEFT$(o$))</syntaxhighlight> |
||
'''Output:''' |
'''Output:''' |
||
<pre> |
<pre> |
||
Line 438: | Line 763: | ||
Walk through the concatenation of the two lists, using backtracking (forced by the ~ operator). |
Walk through the concatenation of the two lists, using backtracking (forced by the ~ operator). |
||
If an element is in both lists, or if the element already is in the accumulated result <code>symdiff</code>, continue. Otherwise add the element to <code>symdiff</code>. When all elements are done and backtracking therefore finally fails, return the contents of <code>symdiff</code>. The flag <code>%</code> in the pattern <code>%@?x</code> ensures that only nontrivial elements (i.e. non-empty strings in this case) are matched. The <code>@</code> flag ensures that at most one string is matched. Together these flags ensure that exactly one element is matched. |
If an element is in both lists, or if the element already is in the accumulated result <code>symdiff</code>, continue. Otherwise add the element to <code>symdiff</code>. When all elements are done and backtracking therefore finally fails, return the contents of <code>symdiff</code>. The flag <code>%</code> in the pattern <code>%@?x</code> ensures that only nontrivial elements (i.e. non-empty strings in this case) are matched. The <code>@</code> flag ensures that at most one string is matched. Together these flags ensure that exactly one element is matched. |
||
< |
<syntaxhighlight lang="bracmat">(SymmetricDifference= |
||
A B x symdiff |
A B x symdiff |
||
. !arg:(?A.?B) |
. !arg:(?A.?B) |
||
Line 453: | Line 778: | ||
? |
? |
||
| !symdiff |
| !symdiff |
||
));</ |
));</syntaxhighlight> |
||
Run: |
Run: |
||
< |
<syntaxhighlight lang="bracmat">SymmetricDifference$(john serena bob mary serena.jim mary john jim bob)</syntaxhighlight> |
||
Output: |
Output: |
||
<lang |
<syntaxhighlight lang="bracmat">serena jim</syntaxhighlight> |
||
=={{header|C}}== |
=={{header|C}}== |
||
Simple method: |
Simple method: |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 512: | Line 837: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight>output |
||
<pre> |
<pre> |
||
A \ B: |
A \ B: |
||
Line 525: | Line 850: | ||
</pre> |
</pre> |
||
If you prefer something elaborate: |
If you prefer something elaborate: |
||
< |
<syntaxhighlight lang="c">#include <assert.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 659: | Line 984: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output |
Output |
||
<pre> |
<pre> |
||
Line 668: | Line 993: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
using System.Linq; |
using System.Linq; |
||
Line 695: | Line 1,020: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 703: | Line 1,028: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <set> |
#include <set> |
||
#include <algorithm> |
#include <algorithm> |
||
Line 726: | Line 1,051: | ||
cout << endl; |
cout << endl; |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
Line 732: | Line 1,057: | ||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure">(use '[clojure.set]) |
||
(defn symmetric-difference [s1 s2] |
(defn symmetric-difference [s1 s2] |
||
(union (difference s1 s2) (difference s2 s1))) |
(union (difference s1 s2) (difference s2 s1))) |
||
(symmetric-difference #{:john :bob :mary :serena} #{:jim :mary :john :bob})</ |
(symmetric-difference #{:john :bob :mary :serena} #{:jim :mary :john :bob})</syntaxhighlight> |
||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">(set-exclusive-or |
||
(remove-duplicates '(John Serena Bob Mary Serena)) |
(remove-duplicates '(John Serena Bob Mary Serena)) |
||
(remove-duplicates '(Jim Mary John Jim Bob)))</ |
(remove-duplicates '(Jim Mary John Jim Bob)))</syntaxhighlight> |
||
Output: |
Output: |
||
(JIM SERENA) |
(JIM SERENA) |
||
Line 748: | Line 1,073: | ||
=={{header|D}}== |
=={{header|D}}== |
||
Generic version. |
Generic version. |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.array; |
||
struct Set(T) { |
struct Set(T) { |
||
Line 774: | Line 1,099: | ||
writeln(" B\\A: ", (B - A).items); |
writeln(" B\\A: ", (B - A).items); |
||
writeln("A symdiff B: ", symmetricDifference(A, B).items); |
writeln("A symdiff B: ", symmetricDifference(A, B).items); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> A\B: ["Serena"] |
<pre> A\B: ["Serena"] |
||
B\A: ["Jim"] |
B\A: ["Jim"] |
||
A symdiff B: ["Serena", "Jim"]</pre> |
A symdiff B: ["Serena", "Jim"]</pre> |
||
=={{header|Datalog}}== |
|||
Implemented using Souffle. |
|||
<syntaxhighlight lang="datalog">.decl A(text: symbol) |
|||
.decl B(text: symbol) |
|||
.decl SymmetricDifference(text: symbol) |
|||
.output SymmetricDifference |
|||
A("this"). |
|||
A("is"). |
|||
A("a"). |
|||
A("test"). |
|||
B("also"). |
|||
B("part"). |
|||
B("of"). |
|||
B("a"). |
|||
B("test"). |
|||
SymmetricDifference(x) :- A(x), !B(x). |
|||
SymmetricDifference(x) :- B(x), !A(x).</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
this |
|||
is |
|||
also |
|||
part |
|||
of |
|||
</pre> |
|||
=={{header|Delphi}}== |
|||
{{libheader| System.Typinfo}} |
|||
{{Trans|Pascal}} |
|||
Small variation of pascal. |
|||
<syntaxhighlight lang="delphi"> |
|||
PROGRAM Symmetric_difference; |
|||
uses |
|||
System.Typinfo; |
|||
TYPE |
|||
TName = (Bob, Jim, John, Mary, Serena); |
|||
TList = SET OF TName; |
|||
TNameHelper = record helper for TName |
|||
FUNCTION ToString(): string; |
|||
end; |
|||
{ TNameHlper } |
|||
FUNCTION TNameHelper.ToString: string; |
|||
BEGIN |
|||
Result := GetEnumName(TypeInfo(TName), Ord(self)); |
|||
END; |
|||
PROCEDURE Put(txt: String; ResSet: TList); |
|||
VAR |
|||
I: TName; |
|||
BEGIN |
|||
Write(txt); |
|||
FOR I IN ResSet DO |
|||
Write(I.ToString, ' '); |
|||
WriteLn; |
|||
END; |
|||
VAR |
|||
ListA: TList = [John, Bob, Mary, Serena]; |
|||
ListB: TList = [Jim, Mary, John, Bob]; |
|||
BEGIN |
|||
Put('ListA -> ', ListA); |
|||
Put('ListB -> ', ListB); |
|||
Put('ListA >< ListB -> ', (ListA - ListB) + (ListB - ListA)); |
|||
Put('ListA - ListB -> ', ListA - ListB); |
|||
Put('ListB - ListA -> ', ListB - ListA); |
|||
ReadLn; |
|||
END.</syntaxhighlight> |
|||
'''Delphi/Object Pascal actually has a 'Symmetric Difference' operator `> <`: ''' |
|||
<syntaxhighlight lang="pascal"> |
|||
program SymmetricDifference; |
|||
type |
|||
charSet = set of Char; |
|||
var |
|||
s1, s2, s3: charSet; |
|||
ch: char; |
|||
begin |
|||
s1 := ['a', 'b', 'c', 'd']; |
|||
s2 := ['c', 'd', 'e', 'f']; |
|||
s3 := s1 >< s2; |
|||
for ch in s3 do |
|||
write(ch, ' '); |
|||
writeLn; |
|||
end. |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
a b e f |
|||
</pre> |
|||
=={{header|Déjà Vu}}== |
=={{header|Déjà Vu}}== |
||
Déjà Vu has no real set type. Instead, it uses a dictionary whose keys are the set values. The <code>set{</code> constructor uses <code>true</code> as a dummy value, and sets <code>false</code> as a dummy value. |
Déjà Vu has no real set type. Instead, it uses a dictionary whose keys are the set values. The <code>set{</code> constructor uses <code>true</code> as a dummy value, and sets <code>false</code> as a dummy value. |
||
< |
<syntaxhighlight lang="dejavu">set :setA set{ :John :Bob :Mary :Serena } |
||
set :setB set{ :Jim :Mary :John :Bob } |
set :setB set{ :Jim :Mary :John :Bob } |
||
Line 795: | Line 1,221: | ||
set{ |
set{ |
||
!. symmetric-difference setA setB</ |
!. symmetric-difference setA setB</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>set{ :Serena :Jim }</pre> |
<pre>set{ :Serena :Jim }</pre> |
||
=={{header|E}}== |
=={{header|E}}== |
||
< |
<syntaxhighlight lang="e">? def symmDiff(a, b) { return (a &! b) | (b &! a) } |
||
# value: <symmDiff> |
# value: <symmDiff> |
||
? symmDiff(["John", "Bob", "Mary", "Serena"].asSet(), ["Jim", "Mary", "John", "Bob"].asSet()) |
? symmDiff(["John", "Bob", "Mary", "Serena"].asSet(), ["Jim", "Mary", "John", "Bob"].asSet()) |
||
# value: ["Jim", "Serena"].asSet()</ |
# value: ["Jim", "Serena"].asSet()</syntaxhighlight> |
||
=={{header|EasyLang}}== |
|||
<syntaxhighlight> |
|||
a$[] = [ "John" "Bob" "Mary" "Serena" ] |
|||
b$[] = [ "Jim" "Mary" "John" "Bob" ] |
|||
# |
|||
for i to 2 |
|||
for a$ in a$[] |
|||
for b$ in b$[] |
|||
if a$ = b$ |
|||
a$ = "" |
|||
break 1 |
|||
. |
|||
. |
|||
if a$ <> "" |
|||
c$[] &= a$ |
|||
. |
|||
. |
|||
swap a$[] b$[] |
|||
. |
|||
print c$[] |
|||
</syntaxhighlight> |
|||
=={{header|Eiffel}}== |
=={{header|Eiffel}}== |
||
<syntaxhighlight lang="eiffel">note |
|||
<lang Eiffel>note |
|||
description: "Summary description for {SYMETRIC_DIFFERENCE_EXAMPLE}." |
description: "Summary description for {SYMETRIC_DIFFERENCE_EXAMPLE}." |
||
URI: "http://rosettacode.org/wiki/Symmetric_difference" |
URI: "http://rosettacode.org/wiki/Symmetric_difference" |
||
Line 851: | Line 1,299: | ||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
{{works with|Elixir|1.2}} |
{{works with|Elixir|1.2}} |
||
< |
<syntaxhighlight lang="elixir">iex(1)> a = ~w[John Bob Mary Serena] |> MapSet.new |
||
#MapSet<["Bob", "John", "Mary", "Serena"]> |
#MapSet<["Bob", "John", "Mary", "Serena"]> |
||
iex(2)> b = ~w[Jim Mary John Bob] |> MapSet.new |
iex(2)> b = ~w[Jim Mary John Bob] |> MapSet.new |
||
Line 862: | Line 1,310: | ||
#Function<12.54118792/2 in :erl_eval.expr/5> |
#Function<12.54118792/2 in :erl_eval.expr/5> |
||
iex(4)> sym_dif.(a,b) |
iex(4)> sym_dif.(a,b) |
||
#MapSet<["Jim", "Serena"]></ |
#MapSet<["Jim", "Serena"]></syntaxhighlight> |
||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
< |
<syntaxhighlight lang="erlang">%% Implemented by Arjun Sunel |
||
-module(symdiff). |
-module(symdiff). |
||
-export([main/0]). |
-export([main/0]). |
||
Line 876: | Line 1,324: | ||
SymmDiffAB = sets:subtract(AUnionB,AIntersectionB), |
SymmDiffAB = sets:subtract(AUnionB,AIntersectionB), |
||
sets:to_list(SymmDiffAB). |
sets:to_list(SymmDiffAB). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 883: | Line 1,331: | ||
=={{header|F Sharp|F#}}== |
=={{header|F Sharp|F#}}== |
||
< |
<syntaxhighlight lang="fsharp">> let a = set ["John"; "Bob"; "Mary"; "Serena"] |
||
let b = set ["Jim"; "Mary"; "John"; "Bob"];; |
let b = set ["Jim"; "Mary"; "John"; "Bob"];; |
||
Line 890: | Line 1,338: | ||
> (a-b) + (b-a);; |
> (a-b) + (b-a);; |
||
val it : Set<string> = set ["Jim"; "Serena"]</ |
val it : Set<string> = set ["Jim"; "Serena"]</syntaxhighlight> |
||
Or, if you don't like the infix operators: |
Or, if you don't like the infix operators: |
||
< |
<syntaxhighlight lang="fsharp">> Set.union (Set.difference a b) (Set.difference b a);; |
||
val it : Set<string> = set ["Jim"; "Serena"]</ |
val it : Set<string> = set ["Jim"; "Serena"]</syntaxhighlight> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
< |
<syntaxhighlight lang="factor">: symmetric-diff ( a b -- c ) |
||
[ diff ] [ swap diff ] 2bi append ; |
[ diff ] [ swap diff ] 2bi append ; |
||
{ "John" "Bob" "Mary" "Serena" } { "Jim" "Mary" "John" "Bob" } symmetric-diff .</ |
{ "John" "Bob" "Mary" "Serena" } { "Jim" "Mary" "John" "Bob" } symmetric-diff .</syntaxhighlight> |
||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
GForth 0.7.0 tested. |
GForth 0.7.0 tested. |
||
< |
<syntaxhighlight lang="forth">: elm ( n -- ; one cell per set ) |
||
[ cell 8 * 1- ] literal umin CREATE 1 swap lshift , |
[ cell 8 * 1- ] literal umin CREATE 1 swap lshift , |
||
DOES> ( -- 2^n ) @ ; |
DOES> ( -- 2^n ) @ ; |
||
Line 926: | Line 1,374: | ||
swap -1 xor and cr persons |
swap -1 xor and cr persons |
||
cr bye |
cr bye |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 938: | Line 1,386: | ||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
{{works with|Fortran|90 and later}} |
{{works with|Fortran|90 and later}} |
||
< |
<syntaxhighlight lang="fortran">program Symmetric_difference |
||
implicit none |
implicit none |
||
Line 959: | Line 1,407: | ||
end do outer2 |
end do outer2 |
||
end program</ |
end program</syntaxhighlight> |
||
Output |
Output |
||
<pre> |
<pre> |
||
Serena |
Serena |
||
Jim |
Jim |
||
</pre> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic"> |
|||
redim shared as string Result(-1) 'represent our sets as strings; |
|||
'this'll do to illustrate the concept |
|||
sub sym( A() as string, B() as string ) |
|||
dim as integer ai, bi, ri |
|||
dim as boolean add_it |
|||
for ai = lbound(A) to ubound(A) |
|||
add_it = true |
|||
for bi = lbound(B) to ubound(B) |
|||
if A(ai) = B(bi) then |
|||
add_it=false |
|||
exit for 'if item is common to both lists, don't include it |
|||
end if |
|||
next bi |
|||
if add_it then |
|||
for ri = 0 to ubound(Result) |
|||
if A(ai) = Result(ri) then |
|||
add_it=false |
|||
exit for |
|||
'if item is already in the result, don't include it again |
|||
end if |
|||
next ri |
|||
end if |
|||
if add_it then |
|||
redim preserve as string Result(0 to ubound(Result)+1) |
|||
Result(ubound(Result)) = A(ai) |
|||
end if |
|||
next ai |
|||
end sub |
|||
dim as string A(0 to 3) = {"John", "Bob", "Mary", "Serena"} |
|||
dim as string B(0 to 4) = {"Jim", "Mary", "John", "Bob", "Jim"} |
|||
'contains a double to show code can handle it |
|||
sym(A(), B()) |
|||
sym(B(), A()) |
|||
for i as uinteger = 0 to ubound(Result) |
|||
print Result(i) |
|||
next i |
|||
</syntaxhighlight> |
|||
{{out}}<pre>Serena |
|||
Jim |
|||
</pre> |
|||
=={{header|Frink}}== |
|||
<syntaxhighlight lang="frink">A = new set["John", "Bob", "Mary", "Serena"] |
|||
B = new set["Jim", "Mary", "John", "Bob"] |
|||
println["Symmetric difference: " + symmetricDifference[A,B]] |
|||
println["A - B : " + setDifference[A,B]] |
|||
println["B - A : " + setDifference[B,A]]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Symmetric difference: [Jim, Serena] |
|||
A - B : [Serena] |
|||
B - A : [Jim] |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
local fn SymmetricDifferenceOfSets( setA as CFSetRef, setB as CFSetRef ) as CFSetRef |
|||
CFMutableSetRef notInSetA = fn MutableSetWithSet( setB ) |
|||
MutableSetMinusSet( notInSetA, setA ) |
|||
CFMutableSetRef notInSetB = fn MutableSetWithSet( setA ) |
|||
MutableSetMinusSet( notInSetB, setB ) |
|||
CFMutableSetRef symmetricDifference = fn MutableSetWithSet( notInSetA ) |
|||
MutableSetUnionSet( symmetricDifference, notInSetB ) |
|||
end fn = fn SetWithSet( symmetricDifference ) |
|||
CFSetRef set1, set2 |
|||
set1 = fn SetWithObjects( @"John", @"Serena", @"Bob", @"Mary", @"Serena", NULL ) |
|||
set2 = fn SetWithObjects( @"Jim", @"Mary", @"John", @"Jim", @"Bob", NULL ) |
|||
NSLog( @"Symmetric difference:\n%@", fn SymmetricDifferenceOfSets( set1, set2 ) ) |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
Symmetric difference: |
|||
{( |
|||
Jim, |
|||
Serena |
|||
)} |
|||
</pre> |
</pre> |
||
=={{header|GAP}}== |
=={{header|GAP}}== |
||
< |
<syntaxhighlight lang="gap">SymmetricDifference := function(a, b) |
||
return Union(Difference(a, b), Difference(b, a)); |
return Union(Difference(a, b), Difference(b, a)); |
||
end; |
end; |
||
Line 974: | Line 1,516: | ||
b := ["Jim", "Mary", "John", "Jim", "Bob"]; |
b := ["Jim", "Mary", "John", "Jim", "Bob"]; |
||
SymmetricDifference(a,b); |
SymmetricDifference(a,b); |
||
[ "Jim", "Serena" ]</ |
[ "Jim", "Serena" ]</syntaxhighlight> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 997: | Line 1,539: | ||
} |
} |
||
fmt.Println(sd) |
fmt.Println(sd) |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,003: | Line 1,545: | ||
</pre> |
</pre> |
||
Alternatively, the following computes destructively on a. The result is the same. |
Alternatively, the following computes destructively on a. The result is the same. |
||
< |
<syntaxhighlight lang="go">func main() { |
||
for e := range b { |
for e := range b { |
||
delete(a, e) |
delete(a, e) |
||
} |
} |
||
fmt.Println(a) |
fmt.Println(a) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Solution: |
Solution: |
||
< |
<syntaxhighlight lang="groovy">def symDiff = { Set s1, Set s2 -> |
||
assert s1 != null |
assert s1 != null |
||
assert s2 != null |
assert s2 != null |
||
(s1 + s2) - (s1.intersect(s2)) |
(s1 + s2) - (s1.intersect(s2)) |
||
}</ |
}</syntaxhighlight> |
||
Test: |
Test: |
||
< |
<syntaxhighlight lang="groovy">Set a = ['John', 'Serena', 'Bob', 'Mary', 'Serena'] |
||
Set b = ['Jim', 'Mary', 'John', 'Jim', 'Bob'] |
Set b = ['Jim', 'Mary', 'John', 'Jim', 'Bob'] |
||
Line 1,110: | Line 1,652: | ||
ppm <> csny: ${PC} |
ppm <> csny: ${PC} |
||
ppm <> ppm: ${PP} |
ppm <> ppm: ${PP} |
||
"""</ |
"""</syntaxhighlight> |
||
Output: |
Output: |
||
Line 1,154: | Line 1,696: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import Data.Set |
||
a = fromList ["John", "Bob", "Mary", "Serena"] |
a = fromList ["John", "Bob", "Mary", "Serena"] |
||
Line 1,161: | Line 1,703: | ||
(-|-) :: Ord a => Set a -> Set a -> Set a |
(-|-) :: Ord a => Set a -> Set a -> Set a |
||
x -|- y = (x \\ y) `union` (y \\ x) |
x -|- y = (x \\ y) `union` (y \\ x) |
||
-- Equivalently: (x `union` y) \\ (x `intersect` y)</ |
-- Equivalently: (x `union` y) \\ (x `intersect` y)</syntaxhighlight> |
||
Symmetric difference: |
Symmetric difference: |
||
< |
<syntaxhighlight lang="haskell">*Main> a -|- b |
||
fromList ["Jim","Serena"]</ |
fromList ["Jim","Serena"]</syntaxhighlight> |
||
Individual differences: |
Individual differences: |
||
< |
<syntaxhighlight lang="haskell">*Main> a \\ b |
||
fromList ["Serena"] |
fromList ["Serena"] |
||
*Main> b \\ a |
*Main> b \\ a |
||
fromList ["Jim"]</ |
fromList ["Jim"]</syntaxhighlight> |
||
=={{header|HicEst}}== |
=={{header|HicEst}}== |
||
< |
<syntaxhighlight lang="hicest">CALL SymmDiff("John,Serena,Bob,Mary,Serena,", "Jim,Mary,John,Jim,Bob,") |
||
CALL SymmDiff("John,Bob,Mary,Serena,", "Jim,Mary,John,Bob,") |
CALL SymmDiff("John,Bob,Mary,Serena,", "Jim,Mary,John,Bob,") |
||
Line 1,191: | Line 1,733: | ||
EDIT(Text=a, Option=1, SortDelDbls=a) ! Option=1: keep case; Serena, |
EDIT(Text=a, Option=1, SortDelDbls=a) ! Option=1: keep case; Serena, |
||
differences = TRIM( differences ) // a |
differences = TRIM( differences ) // a |
||
END</ |
END</syntaxhighlight> |
||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
Set operations are built into Icon/Unicon. |
Set operations are built into Icon/Unicon. |
||
< |
<syntaxhighlight lang="icon">procedure main() |
||
a := set(["John", "Serena", "Bob", "Mary", "Serena"]) |
a := set(["John", "Serena", "Bob", "Mary", "Serena"]) |
||
Line 1,213: | Line 1,755: | ||
write("}") |
write("}") |
||
return |
return |
||
end</ |
end</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre>a = { Serena Mary Bob John } |
<pre>a = { Serena Mary Bob John } |
||
Line 1,222: | Line 1,764: | ||
=={{header|J}}== |
=={{header|J}}== |
||
< |
<syntaxhighlight lang="j"> A=: ~.;:'John Serena Bob Mary Serena' |
||
B=: ~. ;:'Jim Mary John Jim Bob' |
B=: ~. ;:'Jim Mary John Jim Bob' |
||
Line 1,232: | Line 1,774: | ||
┌──────┬───┐ |
┌──────┬───┐ |
||
│Serena│Jim│ |
│Serena│Jim│ |
||
└──────┴───┘</ |
└──────┴───┘</syntaxhighlight> |
||
To illustrate some of the underlying mechanics used here: |
To illustrate some of the underlying mechanics used here: |
||
< |
<syntaxhighlight lang="j"> A -. B NB. items in A but not in B |
||
┌──────┐ |
┌──────┐ |
||
│Serena│ |
│Serena│ |
||
Line 1,245: | Line 1,787: | ||
┌────┬──────┬───┬────┐ |
┌────┬──────┬───┬────┐ |
||
│John│Serena│Bob│Mary│ |
│John│Serena│Bob│Mary│ |
||
└────┴──────┴───┴────┘</ |
└────┴──────┴───┴────┘</syntaxhighlight> |
||
Here's an alternative implementation: |
Here's an alternative implementation: |
||
< |
<syntaxhighlight lang="j"> A (, -. [ -. -.) B |
||
┌──────┬───┐ |
┌──────┬───┐ |
||
│Serena│Jim│ |
│Serena│Jim│ |
||
└──────┴───┘</ |
└──────┴───┘</syntaxhighlight> |
||
Here, <code>(,)</code> contains all items from A and B and <code>([ -. -.)</code> is the idiom for set intersection, and their difference is the symmetric difference. (Note: an individual word in a J sentence may be placed inside a parenthesis with no change in evaluation, and this can also be used for emphasis when a word might get lost.) |
Here, <code>(,)</code> contains all items from A and B and <code>([ -. -.)</code> is the idiom for set intersection, and their difference is the symmetric difference. (Note: an individual word in a J sentence may be placed inside a parenthesis with no change in evaluation, and this can also be used for emphasis when a word might get lost.) |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java">import java.util.Arrays; |
||
import java.util.HashSet; |
import java.util.HashSet; |
||
import java.util.Set; |
import java.util.Set; |
||
Line 1,297: | Line 1,839: | ||
System.out.println("Symmetric Difference 2: " + symmetricDifference2); |
System.out.println("Symmetric Difference 2: " + symmetricDifference2); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>In set A: [Mary, Bob, Serena, John] |
<pre>In set A: [Mary, Bob, Serena, John] |
||
Line 1,316: | Line 1,858: | ||
Uses the Array function <code>unique()</code> defined [[Create a Sequence of unique elements#JavaScript|here]]. |
Uses the Array function <code>unique()</code> defined [[Create a Sequence of unique elements#JavaScript|here]]. |
||
< |
<syntaxhighlight lang="javascript">// in A but not in B |
||
function relative_complement(A, B) { |
function relative_complement(A, B) { |
||
return A.filter(function(elem) {return B.indexOf(elem) == -1}); |
return A.filter(function(elem) {return B.indexOf(elem) == -1}); |
||
Line 1,331: | Line 1,873: | ||
print(a); |
print(a); |
||
print(b); |
print(b); |
||
print(symmetric_difference(a,b));</ |
print(symmetric_difference(a,b));</syntaxhighlight> |
||
outputs |
outputs |
||
<pre>Bob,John,Mary,Serena |
<pre>Bob,John,Mary,Serena |
||
Line 1,339: | Line 1,881: | ||
'''Clear JavaScript''' |
'''Clear JavaScript''' |
||
< |
<syntaxhighlight lang="javascript">function Difference(A,B) |
||
{ |
{ |
||
var a = A.length, b = B.length, c = 0, C = []; |
var a = A.length, b = B.length, c = 0, C = []; |
||
Line 1,367: | Line 1,909: | ||
Difference(B,A); // 'Jim' |
Difference(B,A); // 'Jim' |
||
SymmetricDifference(A,B); // 'Serena','Jim' |
SymmetricDifference(A,B); // 'Serena','Jim' |
||
*/</ |
*/</syntaxhighlight> |
||
===ES6=== |
===ES6=== |
||
====Functional==== |
====Functional==== |
||
By composition of generic functions; |
By composition of generic functions; |
||
< |
<syntaxhighlight lang="javascript">(() => { |
||
'use strict'; |
'use strict'; |
||
Line 1,435: | Line 1,977: | ||
symmetricDifference(a, b) |
symmetricDifference(a, b) |
||
); |
); |
||
})();</ |
})();</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
< |
<syntaxhighlight lang="javascript">["Serena", "Jim"]</syntaxhighlight> |
||
====Procedural ==== |
====Procedural ==== |
||
<syntaxhighlight lang="javascript"> |
|||
<lang JavaScript> |
|||
const symmetricDifference = (...args) => { |
const symmetricDifference = (...args) => { |
||
let result = new Set(); |
let result = new Set(); |
||
Line 1,453: | Line 1,995: | ||
console.log(symmetricDifference([1, 2, 5], [2, 3, 5], [3, 4, 5])); |
console.log(symmetricDifference([1, 2, 5], [2, 3, 5], [3, 4, 5])); |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} |
{{Out}} |
||
< |
<syntaxhighlight lang="javascript">["Jim", "Serena"] |
||
[1, 4, 5] |
[1, 4, 5] |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|jq}}== |
=={{header|jq}}== |
||
Line 1,464: | Line 2,006: | ||
given these assumptions, it is quite efficient. To workaround the |
given these assumptions, it is quite efficient. To workaround the |
||
no-null requirement would be tedious but straightforward. |
no-null requirement would be tedious but straightforward. |
||
< |
<syntaxhighlight lang="jq"># The following implementation of intersection (but not symmetric_difference) assumes that the |
||
# elements of a (and of b) are unique and do not include null: |
# elements of a (and of b) are unique and do not include null: |
||
def intersection(a; b): |
def intersection(a; b): |
||
Line 1,474: | Line 2,016: | ||
(a|unique) as $a | (b|unique) as $b |
(a|unique) as $a | (b|unique) as $b |
||
| (($a + $b) | unique) - (intersection($a;$b)); |
| (($a + $b) | unique) - (intersection($a;$b)); |
||
</syntaxhighlight> |
|||
</lang> |
|||
Example:< |
Example:<syntaxhighlight lang="jq">symmetric_difference( [1,2,1,2]; [2,3] ) |
||
[1,3]</ |
[1,3]</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
{{works with|Julia|0.6}} |
{{works with|Julia|0.6}} |
||
Built-in function. |
Built-in function. |
||
< |
<syntaxhighlight lang="julia">A = ["John", "Bob", "Mary", "Serena"] |
||
B = ["Jim", "Mary", "John", "Bob"] |
B = ["Jim", "Mary", "John", "Bob"] |
||
@show A B symdiff(A, B)</ |
@show A B symdiff(A, B)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,492: | Line 2,034: | ||
=={{header|K}}== |
=={{header|K}}== |
||
< |
<syntaxhighlight lang="k"> A: ?("John";"Bob";"Mary";"Serena") |
||
B: ?("Jim";"Mary";"John";"Bob") |
B: ?("Jim";"Mary";"John";"Bob") |
||
Line 1,501: | Line 2,043: | ||
(A _dvl B;B _dvl A) / Symmetric difference |
(A _dvl B;B _dvl A) / Symmetric difference |
||
("Serena" |
("Serena" |
||
"Jim")</ |
"Jim")</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
fun main(args: Array<String>) { |
fun main(args: Array<String>) { |
||
Line 1,517: | Line 2,059: | ||
val e = c.union(d) |
val e = c.union(d) |
||
println("A Δ B = $e") |
println("A Δ B = $e") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,527: | Line 2,069: | ||
A Δ B = [Serena, Jim] |
A Δ B = [Serena, Jim] |
||
</pre> |
</pre> |
||
=={{header|Ksh}}== |
|||
<syntaxhighlight lang="ksh"> |
|||
#!/bin/ksh |
|||
# Symmetric difference - enumerate the items that are in A or B but not both. |
|||
# # Variables: |
|||
# |
|||
typeset -a A=( John Bob Mary Serena ) |
|||
typeset -a B=( Jim Mary John Bob ) |
|||
# # Functions: |
|||
# |
|||
# # Function _flattenarr(arr, sep) - flatten arr into string by separator sep |
|||
# |
|||
function _flattenarr { |
|||
typeset _arr ; nameref _arr="$1" |
|||
typeset _sep ; typeset -L1 _sep="$2" |
|||
typeset _buff |
|||
typeset _oldIFS=$IFS ; IFS="${_sep}" |
|||
_buff=${_arr[*]} |
|||
IFS="${_oldIFS}" |
|||
echo "${_buff}" |
|||
} |
|||
# # Function _notin(_arr1, _arr2) - elements in arr1 and not in arr2 |
|||
# |
|||
function _notin { |
|||
typeset _ar1 ; nameref _ar1="$1" |
|||
typeset _ar2 ; nameref _ar2="$2" |
|||
typeset _i _buff _set ; integer _i |
|||
_buff=$(_flattenarr _ar2 \|) |
|||
for((_i=0; _i<${#_ar1[*]}; _i++)); do |
|||
[[ ${_ar1[_i]} != @(${_buff}) ]] && _set+="${_ar1[_i]} " |
|||
done |
|||
echo ${_set% *} |
|||
} |
|||
###### |
|||
# main # |
|||
###### |
|||
AnB=$(_notin A B) ; echo "A - B = ${AnB}" |
|||
BnA=$(_notin B A) ; echo "B - A = ${BnA}" |
|||
echo "A xor B = ${AnB} ${BnA}"</syntaxhighlight> |
|||
{{out}}<pre>A - B = Serena |
|||
B - A = Jim |
|||
A xor B = Serena Jim</pre> |
|||
=={{header|Lasso}}== |
=={{header|Lasso}}== |
||
< |
<syntaxhighlight lang="lasso"> |
||
[ |
[ |
||
var( |
var( |
||
Line 1,554: | Line 2,147: | ||
] |
] |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Logo}}== |
=={{header|Logo}}== |
||
{{works with|UCB Logo}} |
{{works with|UCB Logo}} |
||
< |
<syntaxhighlight lang="logo">to diff :a :b [:acc []] |
||
if empty? :a [output sentence :acc :b] |
if empty? :a [output sentence :acc :b] |
||
ifelse member? first :a :b ~ |
ifelse member? first :a :b ~ |
||
Line 1,568: | Line 2,161: | ||
make "b [Jim Mary John Bob] |
make "b [Jim Mary John Bob] |
||
show diff :a :b ; [Serena Jim]</ |
show diff :a :b ; [Serena Jim]</syntaxhighlight> |
||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
< |
<syntaxhighlight lang="lua">A = { ["John"] = true, ["Bob"] = true, ["Mary"] = true, ["Serena"] = true } |
||
B = { ["Jim"] = true, ["Mary"] = true, ["John"] = true, ["Bob"] = true } |
B = { ["Jim"] = true, ["Mary"] = true, ["John"] = true, ["Bob"] = true } |
||
Line 1,589: | Line 2,182: | ||
for b_a in pairs(B_A) do |
for b_a in pairs(B_A) do |
||
print( b_a ) |
print( b_a ) |
||
end</ |
end</syntaxhighlight> |
||
Object-oriented approach: |
Object-oriented approach: |
||
< |
<syntaxhighlight lang="lua">SetPrototype = { |
||
__index = { |
__index = { |
||
union = function(self, other) |
union = function(self, other) |
||
Line 1,648: | Line 2,241: | ||
print("Intersection A∩B : " .. A:intersection(B)) |
print("Intersection A∩B : " .. A:intersection(B)) |
||
print("Difference A\\B : " .. A:difference(B)) |
print("Difference A\\B : " .. A:difference(B)) |
||
print("Difference B\\A : " .. B:difference(A))</ |
print("Difference B\\A : " .. B:difference(A))</syntaxhighlight> |
||
'''Output:''' |
'''Output:''' |
||
Line 1,663: | Line 2,256: | ||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
Maple has built-in support for set operations. Assign the sets A and B: |
Maple has built-in support for set operations. Assign the sets A and B: |
||
< |
<syntaxhighlight lang="maple">A := {John, Bob, Mary, Serena}; |
||
B := {Jim, Mary, John, Bob};</ |
B := {Jim, Mary, John, Bob};</syntaxhighlight> |
||
Now compute the symmetric difference with the '''symmdiff''' command: |
Now compute the symmetric difference with the '''symmdiff''' command: |
||
<lang |
<syntaxhighlight lang="maple">symmdiff(A, B);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
{Jim, Serena} |
{Jim, Serena} |
||
=={{header|Mathematica}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
Mathematica has built-in support for operations on sets, using its generic symbolic lists. This function finds the entries in each list that are not present in the intersection of the two lists. |
Mathematica has built-in support for operations on sets, using its generic symbolic lists. This function finds the entries in each list that are not present in the intersection of the two lists. |
||
< |
<syntaxhighlight lang="mathematica">SymmetricDifference[x_List,y_List] := Join[Complement[x,Intersection[x,y]],Complement[y,Intersection[x,y]]]</syntaxhighlight> |
||
For large lists, some performance improvement could be made by caching the intersection of the two lists to avoid computing it twice: |
For large lists, some performance improvement could be made by caching the intersection of the two lists to avoid computing it twice: |
||
< |
<syntaxhighlight lang="mathematica">CachedSymmetricDifference[x_List,y_List] := Module[{intersect=Intersection[x,y]},Join[Complement[x,intersect],Complement[y,intersect]]]</syntaxhighlight> |
||
Also, due to Mathematica's symbolic nature, these functions are automatically applicable to lists of any content, such as strings, integers, reals, graphics, or undefined generic symbols (e.g. unassigned variables). |
Also, due to Mathematica's symbolic nature, these functions are automatically applicable to lists of any content, such as strings, integers, reals, graphics, or undefined generic symbols (e.g. unassigned variables). |
||
=={{header|MATLAB}}== |
=={{header|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: |
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: |
||
< |
<syntaxhighlight lang="matlab">>> [setdiff([1 2 3],[2 3 4]) setdiff([2 3 4],[1 2 3])] |
||
ans = |
ans = |
||
1 4</ |
1 4</syntaxhighlight> |
||
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. |
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. |
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. |
||
< |
<syntaxhighlight lang="matlab">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' ); |
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' ); |
||
Line 1,778: | Line 2,371: | ||
resultantSet = unique(resultantSet); %Make sure there are not duplicates |
resultantSet = unique(resultantSet); %Make sure there are not duplicates |
||
end %symmetricDifference</ |
end %symmetricDifference</syntaxhighlight> |
||
Solution Test: |
Solution Test: |
||
< |
<syntaxhighlight lang="matlab">>> A = {'John','Bob','Mary','Serena'} |
||
A = |
A = |
||
Line 1,802: | Line 2,395: | ||
ans = |
ans = |
||
1 4 %Correct</ |
1 4 %Correct</syntaxhighlight> |
||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
||
< |
<syntaxhighlight lang="maxima">/* builtin */ |
||
symmdifference({"John", "Bob", "Mary", "Serena"}, |
symmdifference({"John", "Bob", "Mary", "Serena"}, |
||
{"Jim", "Mary", "John", "Bob"}); |
{"Jim", "Mary", "John", "Bob"}); |
||
{"Jim", "Serena"}</ |
{"Jim", "Serena"}</syntaxhighlight> |
||
=={{header|Mercury}}== |
=={{header|Mercury}}== |
||
< |
<syntaxhighlight lang="mercury">:- module symdiff. |
||
:- interface. |
:- interface. |
||
Line 1,831: | Line 2,424: | ||
print_set(Desc, Set, !IO) :- |
print_set(Desc, Set, !IO) :- |
||
to_sorted_list(Set, Elems), |
to_sorted_list(Set, Elems), |
||
io.format("%11s: %s\n", [s(Desc), s(string(Elems))], !IO).</ |
io.format("%11s: %s\n", [s(Desc), s(string(Elems))], !IO).</syntaxhighlight> |
||
=={{header|MiniScript}}== |
|||
<syntaxhighlight lang="miniscript"> |
|||
Set = new map |
|||
Set["set"] = {} |
|||
Set.init = function(items) |
|||
set = new Set |
|||
set.set = {} |
|||
for item in items |
|||
set.add(item) |
|||
end for |
|||
return set |
|||
end function |
|||
Set.contains = function(item) |
|||
return self.set.hasIndex(item) |
|||
end function |
|||
Set.items = function |
|||
return self.set.indexes |
|||
end function |
|||
Set.add = function(item) |
|||
self.set[item] = true |
|||
end function |
|||
Set.union = function(other) |
|||
result = Set.init |
|||
result.set = self.set + other.set |
|||
return result |
|||
end function |
|||
Set.difference = function(other) |
|||
result = Set.init |
|||
for item in self.items |
|||
if not other.contains(item) then result.add(item) |
|||
end for |
|||
return result |
|||
end function |
|||
Set.symmetricDifference = function(other) |
|||
diff1 = self.difference(other) |
|||
diff2 = other.difference(self) |
|||
return diff1.union(diff2) |
|||
end function |
|||
a = ["John", "Serena", "Bob", "Mary", "Serena"] |
|||
b = ["Jim", "Mary", "John", "Jim", "Bob"] |
|||
A1 = Set.init(a) |
|||
B1 = Set.init(b) |
|||
print "A XOR B " + A1.symmetricDifference(B1).items |
|||
print "A - B " + A1.difference(B1).items |
|||
print "B - A " + B1.difference(A1).items |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>A XOR B ["Serena", "Jim"] |
|||
A - B ["Serena"] |
|||
B - A ["Jim"] |
|||
</pre> |
|||
=={{header|Miranda}}== |
|||
<syntaxhighlight lang="miranda>main :: [sys_message] |
|||
main = [Stdout (show (symdiff a b) ++ "\n")] |
|||
where a = ["John", "Serena", "Bob", "Mary", "Serena"] |
|||
b = ["Jim", "Mary", "John", "Jim", "Bob"] |
|||
symdiff :: [*]->[*]->[*] |
|||
symdiff a b = (a' -- b') ++ (b' -- a') |
|||
where a' = nub a |
|||
b' = nub b |
|||
nub :: [*]->[*] |
|||
nub = f [] |
|||
where f acc [] = acc |
|||
f acc (a:as) = f acc as, if a $in acc |
|||
= f (a:acc) as, otherwise |
|||
in :: *->[*]->bool |
|||
in i [] = False |
|||
in i (a:as) = a == i \/ i $in as</syntaxhighlight> |
|||
{{out}} |
|||
<pre>["Serena","Jim"]</pre> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim">import sets |
||
var setA = ["John", "Bob", "Mary", "Serena"]. |
var setA = ["John", "Bob", "Mary", "Serena"].toHashSet |
||
var setB = ["Jim", "Mary", "John", "Bob"]. |
var setB = ["Jim", "Mary", "John", "Bob"].toHashSet |
||
echo setA -+- setB # Symmetric difference |
echo setA -+- setB # Symmetric difference |
||
echo setA - setB # Difference |
echo setA - setB # Difference |
||
echo setB - setA # Difference</ |
echo setB - setA # Difference</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>{Serena, Jim} |
<pre>{Serena, Jim} |
||
Line 1,847: | Line 2,525: | ||
=={{header|Objective-C}}== |
=={{header|Objective-C}}== |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
int main(int argc, const char *argv[]) { |
int main(int argc, const char *argv[]) { |
||
Line 1,876: | Line 2,554: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">let unique lst = |
||
let f lst x = if List.mem x lst then lst else x::lst in |
let f lst x = if List.mem x lst then lst else x::lst in |
||
List.rev (List.fold_left f [] lst) |
List.rev (List.fold_left f [] lst) |
||
Line 1,886: | Line 2,564: | ||
unique (List.filter (fun v -> not (List.mem v b)) a) |
unique (List.filter (fun v -> not (List.mem v b)) a) |
||
let ( -|- ) a b = (b -| a) @ (a -| b)</ |
let ( -|- ) a b = (b -| a) @ (a -| b)</syntaxhighlight> |
||
in the toplevel: |
in the toplevel: |
||
< |
<syntaxhighlight lang="ocaml"># let a = [ "John"; "Bob"; "Mary"; "Serena" ] |
||
and b = [ "Jim"; "Mary"; "John"; "Bob" ] |
and b = [ "Jim"; "Mary"; "John"; "Bob" ] |
||
;; |
;; |
||
Line 1,901: | Line 2,579: | ||
# b -| a ;; |
# b -| a ;; |
||
- : string list = ["Jim"]</ |
- : string list = ["Jim"]</syntaxhighlight> |
||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
||
< |
<syntaxhighlight lang="oorexx">a = .set~of("John", "Bob", "Mary", "Serena") |
||
b = .set~of("Jim", "Mary", "John", "Bob") |
b = .set~of("Jim", "Mary", "John", "Bob") |
||
-- the xor operation is a symmetric difference |
-- the xor operation is a symmetric difference |
||
do item over a~xor(b) |
do item over a~xor(b) |
||
say item |
say item |
||
end</ |
end</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,918: | Line 2,596: | ||
=={{header|Oz}}== |
=={{header|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: |
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: |
||
< |
<syntaxhighlight lang="oz">declare |
||
fun {SymDiff A B} |
fun {SymDiff A B} |
||
{Union {Diff A B} {Diff B A}} |
{Union {Diff A B} {Diff B A}} |
||
Line 1,949: | Line 2,627: | ||
{Show {SymDiff |
{Show {SymDiff |
||
{MakeSet [john serena bob mary serena]} |
{MakeSet [john serena bob mary serena]} |
||
{MakeSet [jim mary john jim bob]}}}</ |
{MakeSet [jim mary john jim bob]}}}</syntaxhighlight> |
||
Oz <em>does</em> 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: |
Oz <em>does</em> 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: |
||
< |
<syntaxhighlight lang="oz">declare |
||
fun {SymDiff A B} |
fun {SymDiff A B} |
||
{FS.union {FS.diff A B} {FS.diff B A}} |
{FS.union {FS.diff A B} {FS.diff B A}} |
||
Line 1,959: | Line 2,637: | ||
B = {FS.value.make [5 3 1 2]} |
B = {FS.value.make [5 3 1 2]} |
||
in |
in |
||
{Show {SymDiff A B}}</ |
{Show {SymDiff A B}}</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
< |
<syntaxhighlight lang="parigp">sd(u,v)={ |
||
my(r=List()); |
my(r=List()); |
||
u=vecsort(u,,8); |
u=vecsort(u,,8); |
||
Line 1,970: | Line 2,648: | ||
Vec(r) |
Vec(r) |
||
}; |
}; |
||
sd(["John", "Serena", "Bob", "Mary", "Serena"],["Jim", "Mary", "John", "Jim", "Bob"])</ |
sd(["John", "Serena", "Bob", "Mary", "Serena"],["Jim", "Mary", "John", "Jim", "Bob"])</syntaxhighlight> |
||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
{{works with|FPC 3.0.2}} |
{{works with|FPC 3.0.2}} |
||
< |
<syntaxhighlight lang="pascal">PROGRAM Symmetric_difference; |
||
TYPE |
TYPE |
||
Line 1,997: | Line 2,675: | ||
Put('ListA -> ', ListA); |
Put('ListA -> ', ListA); |
||
Put('ListB -> ', ListB); |
Put('ListB -> ', ListB); |
||
Put('ListA >< ListB -> ', ListA |
Put('ListA >< ListB -> ', (ListA - ListB) + (ListB - ListA)); |
||
Put('ListA - ListB -> ', ListA - ListB); |
Put('ListA - ListB -> ', ListA - ListB); |
||
Put('ListB - ListA -> ', ListB - ListA); |
Put('ListB - ListA -> ', ListB - ListA); |
||
ReadLn; |
ReadLn; |
||
END.</ |
END.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>ListA -> Bob John Mary Serena |
<pre>ListA -> Bob John Mary Serena |
||
Line 2,008: | Line 2,686: | ||
ListA - ListB -> Serena |
ListA - ListB -> Serena |
||
ListB - ListA -> Jim</pre> |
ListB - ListA -> Jim</pre> |
||
'''Object Pascal actually has a 'Symmetric Difference' operator `> <`: ''' |
|||
<syntaxhighlight lang="pascal"> |
|||
program SymmetricDifference; |
|||
type |
|||
charSet = set of Char; |
|||
var |
|||
s1, s2, s3: charSet; |
|||
ch: char; |
|||
begin |
|||
s1 := ['a', 'b', 'c', 'd']; |
|||
s2 := ['c', 'd', 'e', 'f']; |
|||
s3 := s1 >< s2; |
|||
for ch in s3 do |
|||
write(ch, ' '); |
|||
writeLn; |
|||
end. |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
a b e f |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">sub symm_diff { |
||
# two lists passed in as references |
# two lists passed in as references |
||
my %in_a = map(($_=>1), @{+shift}); |
my %in_a = map(($_=>1), @{+shift}); |
||
Line 2,026: | Line 2,729: | ||
my ($a, $b, $s) = symm_diff(\@a, \@b); |
my ($a, $b, $s) = symm_diff(\@a, \@b); |
||
print "A\\B: @$a\nB\\A: @$b\nSymm: @$s\n";</ |
print "A\\B: @$a\nB\\A: @$b\nSymm: @$s\n";</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>A\B: Serena |
<pre>A\B: Serena |
||
Line 2,033: | Line 2,736: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<lang Phix>function Union(sequence a, sequence b) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">Union</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
for i=1 to length(a) do |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
if not find(a[i],b) then |
|||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
b = append(b,a[i]) |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
return b |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">b</span> |
|||
end function |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
function Difference(sequence a, sequence b) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">Difference</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
sequence res = {} |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for i=1 to length(a) do |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
if not find(a[i],b) |
|||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
and not find(a[i],res) then |
|||
<span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
res = append(res,a[i]) |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
return res |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span> |
|||
end function |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
function Symmetric_Difference(sequence a, sequence b) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">Symmetric_Difference</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
return Union(Difference(a, b), Difference(b, a)) |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">Union</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">))</span> |
|||
end function |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
sequence a = {"John", "Serena", "Bob", "Mary", "Serena"}, |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"John"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Serena"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bob"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Mary"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Serena"</span><span style="color: #0000FF;">},</span> |
|||
b = {"Jim", "Mary", "John", "Jim", "Bob"} |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Jim"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Mary"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"John"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Jim"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bob"</span><span style="color: #0000FF;">}</span> |
|||
?Symmetric_Difference(a,a) |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">Symmetric_Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> |
|||
?Symmetric_Difference(a,b) |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">Symmetric_Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
?Symmetric_Difference(b,a) |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">Symmetric_Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> |
|||
?Symmetric_Difference(b,b)</lang> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">Symmetric_Difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 2,070: | Line 2,775: | ||
{} |
{} |
||
</pre> |
</pre> |
||
You can also use the builtin (which defaults to symmetic differences), though it will crash if you pass it "sets" with duplicate elements. |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"John"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Serena"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bob"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Mary"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Jim"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Mary"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"John"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bob"</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">difference</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
<!--</syntaxhighlight>--> |
|||
Same output as above |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"><?php |
||
$a = array('John', 'Bob', 'Mary', 'Serena'); |
$a = array('John', 'Bob', 'Mary', 'Serena'); |
||
$b = array('Jim', 'Mary', 'John', 'Bob'); |
$b = array('Jim', 'Mary', 'John', 'Bob'); |
||
Line 2,093: | Line 2,809: | ||
"\nB \\ A: ", implode(', ', $b_minus_a), |
"\nB \\ A: ", implode(', ', $b_minus_a), |
||
"\nSymmetric difference: ", implode(', ', $symmetric_difference), "\n"; |
"\nSymmetric difference: ", implode(', ', $symmetric_difference), "\n"; |
||
?></ |
?></syntaxhighlight> |
||
This outputs: |
This outputs: |
||
<pre>List A: John, Bob, Mary, Serena |
<pre>List A: John, Bob, Mary, Serena |
||
Line 2,100: | Line 2,816: | ||
B \ A: Jim |
B \ A: Jim |
||
Symmetric difference: Serena, Jim</pre> |
Symmetric difference: Serena, Jim</pre> |
||
=={{header|Picat}}== |
|||
Using the <code>ordset</code> module. |
|||
<syntaxhighlight lang="picat">import ordset. |
|||
go => |
|||
A = ["John", "Serena", "Bob", "Mary", "Serena"].new_ordset(), |
|||
B = ["Jim", "Mary", "John", "Jim", "Bob"].new_ordset(), |
|||
println(symmetric_difference=symmetric_difference(A,B)), |
|||
println(symmetric_difference2=symmetric_difference2(A,B)), |
|||
println(subtractAB=subtract(A,B)), |
|||
println(subtractBA=subtract(B,A)), |
|||
println(union=union(A,B)), |
|||
println(intersection=intersection(A,B)), |
|||
nl. |
|||
symmetric_difference(A,B) = union(subtract(A,B), subtract(B,A)). |
|||
% variant |
|||
symmetric_difference2(A,B) = subtract(union(A,B), intersection(B,A)).</syntaxhighlight> |
|||
{{out}} |
|||
<pre>symmetric_difference = [Jim,Serena] |
|||
symmetric_difference2 = [Jim,Serena] |
|||
subtractAB = [Serena] |
|||
subtractBA = [Jim] |
|||
union = [Bob,Jim,John,Mary,Serena] |
|||
intersection = [Bob,John,Mary]</pre> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(de symdiff (A B) |
||
(uniq (conc (diff A B) (diff B A))) )</ |
(uniq (conc (diff A B) (diff B A))) )</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>(symdiff '(John Serena Bob Mary Serena) '(Jim Mary John Jim Bob)) |
<pre>(symdiff '(John Serena Bob Mary Serena) '(Jim Mary John Jim Bob)) |
||
Line 2,110: | Line 2,856: | ||
=={{header|Pike}}== |
=={{header|Pike}}== |
||
The set type in Pike is 'multiset', that is, a value may appear multiple times and the difference operator only removes equal amounts of duplicates. |
The set type in Pike is 'multiset', that is, a value may appear multiple times and the difference operator only removes equal amounts of duplicates. |
||
< |
<syntaxhighlight lang="pike">> multiset(string) A = (< "John", "Serena", "Bob", "Mary", "Bob", "Serena" >); |
||
> multiset(string) B = (< "Jim", "Mary", "Mary", "John", "Bob", "Jim" >); |
> multiset(string) B = (< "Jim", "Mary", "Mary", "John", "Bob", "Jim" >); |
||
> A^B; |
> A^B; |
||
Result: (< "Bob", "Serena", "Serena", "Mary", "Jim", "Jim" >)</ |
Result: (< "Bob", "Serena", "Serena", "Mary", "Jim", "Jim" >)</syntaxhighlight> |
||
The <code>^</code> operator treats arrays like multisets. |
The <code>^</code> operator treats arrays like multisets. |
||
< |
<syntaxhighlight lang="pike">> array(string) A = ({ "John", "Serena", "Bob", "Mary", "Serena", "Bob" }); |
||
> array(string) B = ({ "Jim", "Mary", "John", "Jim", "Bob", "Mary" }); |
> array(string) B = ({ "Jim", "Mary", "John", "Jim", "Bob", "Mary" }); |
||
> A^B; |
> A^B; |
||
Line 2,122: | Line 2,868: | ||
> Array.uniq((A-B)+(B-A)); |
> Array.uniq((A-B)+(B-A)); |
||
Result: ({ "Serena", "Jim" })</ |
Result: ({ "Serena", "Jim" })</syntaxhighlight> |
||
Set operations are also possible with mappings. Here the difference operator works as expected: |
Set operations are also possible with mappings. Here the difference operator works as expected: |
||
< |
<syntaxhighlight lang="pike">> mapping(string:int) A = ([ "John":1, "Serena":1, "Bob":1, "Mary":1 ]); |
||
> mapping(string:int) B = ([ "Jim":1, "Mary":1, "John":1, "Bob":1 ]); |
> mapping(string:int) B = ([ "Jim":1, "Mary":1, "John":1, "Bob":1 ]); |
||
> A^B; |
> A^B; |
||
Result: ([ "Jim": 1, "Serena": 1 ])</ |
Result: ([ "Jim": 1, "Serena": 1 ])</syntaxhighlight> |
||
Lastly, there is a Set class. |
Lastly, there is a Set class. |
||
< |
<syntaxhighlight lang="pike">> ADT.Set A = ADT.Set((< "John", "Serena", "Bob", "Mary", "Serena", "Bob" >)); |
||
> ADT.Set B = ADT.Set((< "Jim", "Mary", "John", "Jim", "Bob", "Mary" >)); |
> ADT.Set B = ADT.Set((< "Jim", "Mary", "John", "Jim", "Bob", "Mary" >)); |
||
> (A-B)+(B-A); |
> (A-B)+(B-A); |
||
Result: ADT.Set({ "Serena", "Jim" })</ |
Result: ADT.Set({ "Serena", "Jim" })</syntaxhighlight> |
||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
< |
<syntaxhighlight lang="pli">/* PL/I *************************************************************** |
||
* 17.08.2013 Walter Pachl |
* 17.08.2013 Walter Pachl |
||
**********************************************************************/ |
**********************************************************************/ |
||
Line 2,156: | Line 2,902: | ||
End; |
End; |
||
End; |
End; |
||
End;</ |
End;</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,164: | Line 2,910: | ||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
< |
<syntaxhighlight lang="powershell">$A = @( "John" |
||
"Bob" |
"Bob" |
||
"Mary" |
"Mary" |
||
Line 2,184: | Line 2,930: | ||
# B - A |
# B - A |
||
Compare $A $B | Where SideIndicator -eq "=>" | Select -ExpandProperty InputObject</ |
Compare $A $B | Where SideIndicator -eq "=>" | Select -ExpandProperty InputObject</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>InputObject SideIndicator |
<pre>InputObject SideIndicator |
||
Line 2,202: | Line 2,948: | ||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
{{Works with|SWI-Prolog}} |
{{Works with|SWI-Prolog}} |
||
< |
<syntaxhighlight lang="prolog">sym_diff :- |
||
A = ['John', 'Serena', 'Bob', 'Mary', 'Serena'], |
A = ['John', 'Serena', 'Bob', 'Mary', 'Serena'], |
||
B = ['Jim', 'Mary', 'John', 'Jim', 'Bob'], |
B = ['Jim', 'Mary', 'John', 'Jim', 'Bob'], |
||
Line 2,216: | Line 2,962: | ||
format('difference B\\A : ~w~n', [DBA]), |
format('difference B\\A : ~w~n', [DBA]), |
||
union(DAB, DBA, Diff), |
union(DAB, DBA, Diff), |
||
format('symetric difference : ~w~n', [Diff]).</ |
format('symetric difference : ~w~n', [Diff]).</syntaxhighlight> |
||
output : |
output : |
||
<pre>A : [John,Serena,Bob,Mary,Serena] |
<pre>A : [John,Serena,Bob,Mary,Serena] |
||
Line 2,229: | Line 2,975: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
===Simple approach=== |
===Simple approach=== |
||
< |
<syntaxhighlight lang="purebasic">Dim A.s(3) |
||
Dim B.s(3) |
Dim B.s(3) |
||
Line 2,253: | Line 2,999: | ||
EndIf |
EndIf |
||
Next a |
Next a |
||
Next b</ |
Next b</syntaxhighlight> |
||
===Solution using lists=== |
===Solution using lists=== |
||
< |
<syntaxhighlight lang="purebasic">DataSection |
||
SetA: |
SetA: |
||
Data.i 4 |
Data.i 4 |
||
Line 2,327: | Line 3,073: | ||
Input() |
Input() |
||
CloseConsole() |
CloseConsole() |
||
EndIf</ |
EndIf</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre>Set A: John, Bob, Mary, Serena |
<pre>Set A: John, Bob, Mary, Serena |
||
Line 2,338: | Line 3,084: | ||
'''Python 3.x''' and '''Python 2.7''' have syntax for set literals: |
'''Python 3.x''' and '''Python 2.7''' have syntax for set literals: |
||
< |
<syntaxhighlight lang="python">>>> setA = {"John", "Bob", "Mary", "Serena"} |
||
>>> setB = {"Jim", "Mary", "John", "Bob"} |
>>> setB = {"Jim", "Mary", "John", "Bob"} |
||
>>> setA ^ setB # symmetric difference of A and B |
>>> setA ^ setB # symmetric difference of A and B |
||
Line 2,349: | Line 3,095: | ||
{'John', 'Bob', 'Jim', 'Serena', 'Mary'} |
{'John', 'Bob', 'Jim', 'Serena', 'Mary'} |
||
>>> setA & setB # elements in both A and B (intersection) |
>>> setA & setB # elements in both A and B (intersection) |
||
{'Bob', 'John', 'Mary'}</ |
{'Bob', 'John', 'Mary'}</syntaxhighlight> |
||
Note that the order of set elements is undefined. |
Note that the order of set elements is undefined. |
||
Line 2,355: | Line 3,101: | ||
Earlier versions of Python: |
Earlier versions of Python: |
||
< |
<syntaxhighlight lang="python">>>> setA = set(["John", "Bob", "Mary", "Serena"]) |
||
>>> setB = set(["Jim", "Mary", "John", "Bob"]) |
>>> setB = set(["Jim", "Mary", "John", "Bob"]) |
||
>>> setA ^ setB # symmetric difference of A and B |
>>> setA ^ setB # symmetric difference of A and B |
||
Line 2,361: | Line 3,107: | ||
>>> setA - setB # elements in A that are not in B |
>>> setA - setB # elements in A that are not in B |
||
set(['Serena']) |
set(['Serena']) |
||
>>> # and so on...</ |
>>> # and so on...</syntaxhighlight> |
||
There is also a method call interface for these operations. In contrast to the operators above, they accept any iterables as arguments not just sets. |
There is also a method call interface for these operations. In contrast to the operators above, they accept any iterables as arguments not just sets. |
||
< |
<syntaxhighlight lang="python">>>> setA.symmetric_difference(setB) |
||
{'Jim', 'Serena'} |
{'Jim', 'Serena'} |
||
>>> setA.difference(setB) |
>>> setA.difference(setB) |
||
Line 2,374: | Line 3,120: | ||
{'Jim', 'Mary', 'Serena', 'John', 'Bob'} |
{'Jim', 'Mary', 'Serena', 'John', 'Bob'} |
||
>>> setA.intersection(setB) |
>>> setA.intersection(setB) |
||
{'Mary', 'John', 'Bob'}</ |
{'Mary', 'John', 'Bob'}</syntaxhighlight> |
||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="quackery"> [ $ "rosetta/bitwisesets.qky" loadfile ] now! |
|||
( i.e. using the Quackery code for sets at |
|||
http://rosettacode.org/wiki/Set#Indexed_Bitmaps ) |
|||
set{ John Bob Mary Serena }set is A ( --> { ) |
|||
set{ Jim Mary John Bob }set is B ( --> { ) |
|||
say "A \ B is " A B difference echoset cr |
|||
say "B \ A is " B A difference echoset cr |
|||
say "(A \ B) U (B \ A) is " |
|||
A B difference B A difference union echoset cr |
|||
say "(A U B) \ (A n B) is " |
|||
A B union A B intersection difference echoset cr |
|||
say "Using built-in symmetric difference: " |
|||
A B symmdiff echoset cr </syntaxhighlight> |
|||
{{out}} |
|||
<pre>A \ B is { Serena } |
|||
B \ A is { Jim } |
|||
(A \ B) U (B \ A) is { Jim Serena } |
|||
(A U B) \ (A n B) is { Jim Serena } |
|||
Using built-in symmetric difference: { Jim Serena } |
|||
</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |
||
< |
<syntaxhighlight lang="r">a <- c( "John", "Bob", "Mary", "Serena" ) |
||
b <- c( "Jim", "Mary", "John", "Bob" ) |
b <- c( "Jim", "Mary", "John", "Bob" ) |
||
c(setdiff(b, a), setdiff(a, b)) |
c(setdiff(b, a), setdiff(a, b)) |
||
Line 2,383: | Line 3,162: | ||
a <- c("John", "Serena", "Bob", "Mary", "Serena") |
a <- c("John", "Serena", "Bob", "Mary", "Serena") |
||
b <- c("Jim", "Mary", "John", "Jim", "Bob") |
b <- c("Jim", "Mary", "John", "Jim", "Bob") |
||
c(setdiff(b, a), setdiff(a, b)) </ |
c(setdiff(b, a), setdiff(a, b)) </syntaxhighlight> |
||
In both cases answer is: |
In both cases answer is: |
||
< |
<syntaxhighlight lang="r">[1] "Jim" "Serena"</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(define A (set "John" "Bob" "Mary" "Serena")) |
(define A (set "John" "Bob" "Mary" "Serena")) |
||
Line 2,397: | Line 3,176: | ||
(set-subtract A B) |
(set-subtract A B) |
||
(set-subtract B A) |
(set-subtract B A) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
<lang |
<syntaxhighlight lang="raku" line>my \A = set <John Serena Bob Mary Serena>; |
||
my \B = set <Jim Mary John Jim Bob>; |
my \B = set <Jim Mary John Jim Bob>; |
||
Line 2,407: | Line 3,186: | ||
say B ∖ A; # Set subtraction |
say B ∖ A; # Set subtraction |
||
say (A ∪ B) ∖ (A ∩ B); # Symmetric difference, via basic set operations |
say (A ∪ B) ∖ (A ∩ B); # Symmetric difference, via basic set operations |
||
say A ⊖ B; # Symmetric difference, via dedicated operator</ |
say A ⊖ B; # Symmetric difference, via dedicated operator</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>set(Serena) |
<pre>set(Serena) |
||
Line 2,415: | Line 3,194: | ||
=={{header|REBOL}}== |
=={{header|REBOL}}== |
||
< |
<syntaxhighlight lang="rebol">a: [John Serena Bob Mary Serena] |
||
b: [Jim Mary John Jim Bob] |
b: [Jim Mary John Jim Bob] |
||
difference a b</ |
difference a b</syntaxhighlight> |
||
Result is |
Result is |
||
<pre> |
<pre> |
||
Line 2,423: | Line 3,202: | ||
</pre> |
</pre> |
||
=={{header|Refal}}== |
|||
<syntaxhighlight lang="refal">$ENTRY Go { |
|||
, John Bob Mary Serena: e.A |
|||
, Jim Mary John Bob: e.B |
|||
= <Prout <Symdiff (e.A) (e.B)>>; |
|||
}; |
|||
Symdiff { |
|||
(e.1) (e.2), <Diff (<Set e.1>) (<Set e.2>)>: e.3 |
|||
, <Diff (<Set e.2>) (<Set e.1>)>: e.4 |
|||
= <Union (e.3) (e.4)>; |
|||
}; |
|||
Set { |
|||
= ; |
|||
s.1 e.1 s.1 e.2 = <Set e.1 s.1 e.2>; |
|||
s.1 e.1 = s.1 <Set e.1>; |
|||
}; |
|||
Union { |
|||
(e.1) (e.2) = <Set e.1 e.2>; |
|||
}; |
|||
Diff { |
|||
() (e.1) = ; |
|||
(e.1) () = e.1; |
|||
(s.1 e.1) (e.2 s.1 e.3) = <Diff (e.1) (e.2 e.3)>; |
|||
(s.1 e.1) (e.2) = s.1 <Diff (e.1) (e.2)>; |
|||
};</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Serena Jim</pre> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
===version 1=== |
===version 1=== |
||
Line 2,430: | Line 3,240: | ||
The '''set''' elements may contain any character permitted with a REXX literal, including the literal character itself (expressed as a double literal delimiter), blanks, brackets, commas, and also a ''null'' value. |
The '''set''' elements may contain any character permitted with a REXX literal, including the literal character itself (expressed as a double literal delimiter), blanks, brackets, commas, and also a ''null'' value. |
||
< |
<syntaxhighlight lang="rexx">/*REXX program finds symmetric difference and symmetric AND (between two lists). */ |
||
a= '["John", "Serena", "Bob", "Mary", "Serena"]' /*note the duplicate element: Serena */ |
a= '["John", "Serena", "Bob", "Mary", "Serena"]' /*note the duplicate element: Serena */ |
||
b= '["Jim", "Mary", "John", "Jim", "Bob"]' /* " " " " Jim */ |
b= '["Jim", "Mary", "John", "Jim", "Bob"]' /* " " " " Jim */ |
||
Line 2,466: | Line 3,276: | ||
say /* [↓] SA ≡ symmetric AND. */ |
say /* [↓] SA ≡ symmetric AND. */ |
||
SA= "["strip( strip(SA), 'T', ",")']' /*clean up and add brackets [ ] to it.*/ |
SA= "["strip( strip(SA), 'T', ",")']' /*clean up and add brackets [ ] to it.*/ |
||
say ' symmetric AND =' SA /*stick a fork in it, we're all done. */</ |
say ' symmetric AND =' SA /*stick a fork in it, we're all done. */</syntaxhighlight> |
||
{{out|output|text= when using the in-program lists:}} |
{{out|output|text= when using the in-program lists:}} |
||
<pre> |
<pre> |
||
Line 2,479: | Line 3,289: | ||
===version 1.5=== |
===version 1.5=== |
||
This REXX version shows the symmetric difference and symmetric AND between two lists, the lists have items that have imbedded blanks in them as well as some punctuation, and also a ''null'' element. |
This REXX version shows the symmetric difference and symmetric AND between two lists, the lists have items that have imbedded blanks in them as well as some punctuation, and also a ''null'' element. |
||
< |
<syntaxhighlight lang="rexx">/*REXX pgm finds symmetric difference and symm. AND (between two lists).*/ |
||
a.=0 /*falsify the booleans*/ |
a.=0 /*falsify the booleans*/ |
||
a= '["Zahn", "Yi", "Stands with a Fist", "", "Hungry Wolf", "Yi"]' |
a= '["Zahn", "Yi", "Stands with a Fist", "", "Hungry Wolf", "Yi"]' |
||
Line 2,485: | Line 3,295: | ||
∙ |
∙ |
||
∙ |
∙ |
||
∙</ |
∙</syntaxhighlight> |
||
{{out|output|text= when using the in-program lists (which has imbedded blanks):}} |
{{out|output|text= when using the in-program lists (which has imbedded blanks):}} |
||
<pre> |
<pre> |
||
Line 2,497: | Line 3,307: | ||
===version 2=== |
===version 2=== |
||
< |
<syntaxhighlight lang="rexx">/* REXX --------------------------------------------------------------- |
||
* 14.12.2013 Walter Pachl a short solution |
* 14.12.2013 Walter Pachl a short solution |
||
* 16.12.2013 fix duplicate element problem in input |
* 16.12.2013 fix duplicate element problem in input |
||
Line 2,521: | Line 3,331: | ||
out: parse Arg e |
out: parse Arg e |
||
If wordpos(e,res)=0 Then res=res e |
If wordpos(e,res)=0 Then res=res e |
||
Return</ |
Return</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>Serena Jim</pre> |
<pre>Serena Jim</pre> |
||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
alist = [] |
alist = [] |
||
blist = [] |
blist = [] |
||
Line 2,556: | Line 3,366: | ||
see "b-a :" see nl |
see "b-a :" see nl |
||
see blist2 see nl |
see blist2 see nl |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|RPL}}== |
|||
<code>DIFFL</code> is defined at [[Set#RPL|Set]] |
|||
{{works with|Halcyon Calc|4.2.9}} |
|||
≪ DUP2 <span style="color:blue>DIFFL</span> |
|||
ROT ROT SWAP <span style="color:blue>DIFFL</span> + |
|||
≫ ≫ '<span style="color:blue>SYMDIFF</span>' STO |
|||
{"John" "Bob" "Mary" "Serena"} {"Jim" "Mary" "John" "Bob"} <span style="color:blue>SYMDIFF</span> |
|||
{{out}} |
|||
<pre> |
|||
1: {"Jim" "Serena"} |
|||
</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
With arrays: |
With arrays: |
||
< |
<syntaxhighlight lang="ruby">a = ["John", "Serena", "Bob", "Mary", "Serena"] |
||
b = ["Jim", "Mary", "John", "Jim", "Bob"] |
b = ["Jim", "Mary", "John", "Jim", "Bob"] |
||
# the union minus the intersection: |
# the union minus the intersection: |
||
p sym_diff = (a | b)-(a & b) # => ["Serena", "Jim"]</ |
p sym_diff = (a | b)-(a & b) # => ["Serena", "Jim"]</syntaxhighlight> |
||
Class Set has a symmetric difference operator built-in: |
Class Set has a symmetric difference operator built-in: |
||
< |
<syntaxhighlight lang="ruby">require 'set' |
||
a = Set["John", "Serena", "Bob", "Mary", "Serena"] #Set removes duplicates |
a = Set["John", "Serena", "Bob", "Mary", "Serena"] #Set removes duplicates |
||
b = Set["Jim", "Mary", "John", "Jim", "Bob"] |
b = Set["Jim", "Mary", "John", "Jim", "Bob"] |
||
p sym_diff = a ^ b # => #<Set: {"Jim", "Serena"}></ |
p sym_diff = a ^ b # => #<Set: {"Jim", "Serena"}></syntaxhighlight> |
||
=={{header|Run BASIC}}== |
=={{header|Run BASIC}}== |
||
< |
<syntaxhighlight lang="runbasic"> |
||
setA$ = "John,Bob,Mary,Serena" |
setA$ = "John,Bob,Mary,Serena" |
||
setB$ = "Jim,Mary,John,Bob" |
setB$ = "Jim,Mary,John,Bob" |
||
Line 2,591: | Line 3,414: | ||
i = i + 1 |
i = i + 1 |
||
wend |
wend |
||
end function</ |
end function</syntaxhighlight> |
||
<pre> |
<pre> |
||
Jim |
Jim |
||
Serena |
Serena |
||
Jim,Serena |
Jim,Serena |
||
</pre> |
|||
=={{header|Rust}}== |
|||
Both set types in the std-lib -- <b>HashSet</b> and <b>BTreeSet</b> -- implement a symmetric_difference method. |
|||
<syntaxhighlight lang="rust">use std::collections::HashSet; |
|||
fn main() { |
|||
let a: HashSet<_> = ["John", "Bob", "Mary", "Serena"] |
|||
.iter() |
|||
.collect(); |
|||
let b = ["Jim", "Mary", "John", "Bob"] |
|||
.iter() |
|||
.collect(); |
|||
let diff = a.symmetric_difference(&b); |
|||
println!("{:?}", diff); |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
["Serena", "Jim"] |
|||
</pre> |
</pre> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">scala> val s1 = Set("John", "Serena", "Bob", "Mary", "Serena") |
||
s1: scala.collection.immutable.Set[java.lang.String] = Set(John, Serena, Bob, Mary) |
s1: scala.collection.immutable.Set[java.lang.String] = Set(John, Serena, Bob, Mary) |
||
Line 2,606: | Line 3,453: | ||
scala> (s1 diff s2) union (s2 diff s1) |
scala> (s1 diff s2) union (s2 diff s1) |
||
res46: scala.collection.immutable.Set[java.lang.String] = Set(Serena, Jim)</ |
res46: scala.collection.immutable.Set[java.lang.String] = Set(Serena, Jim)</syntaxhighlight> |
||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
Line 2,614: | Line 3,461: | ||
In pure Scheme, to illustrate implementation of the algorithms: |
In pure Scheme, to illustrate implementation of the algorithms: |
||
< |
<syntaxhighlight lang="scheme"> |
||
(import (scheme base) |
(import (scheme base) |
||
(scheme write)) |
(scheme write)) |
||
Line 2,645: | Line 3,492: | ||
(display (symmetric-difference '(John Serena Bob Mary Serena) |
(display (symmetric-difference '(John Serena Bob Mary Serena) |
||
'(Jim Mary John Jim Bob))) (newline) |
'(Jim Mary John Jim Bob))) (newline) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 2,661: | Line 3,508: | ||
SRFI 1 is one of the most popular SRFIs. It deals with lists, but also has functions treating lists as sets. The lset functions assume the inputs are sets, so we must delete duplicates if this property is not guaranteed on input. |
SRFI 1 is one of the most popular SRFIs. It deals with lists, but also has functions treating lists as sets. The lset functions assume the inputs are sets, so we must delete duplicates if this property is not guaranteed on input. |
||
< |
<syntaxhighlight lang="scheme"> |
||
(import (scheme base) |
(import (scheme base) |
||
(scheme write) |
(scheme write) |
||
Line 2,687: | Line 3,534: | ||
(display (symmetric-difference '(John Serena Bob Mary Serena) |
(display (symmetric-difference '(John Serena Bob Mary Serena) |
||
'(Jim Mary John Jim Bob))) (newline) |
'(Jim Mary John Jim Bob))) (newline) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
< |
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
||
const type: striSet is set of string; |
const type: striSet is set of string; |
||
Line 2,702: | Line 3,549: | ||
begin |
begin |
||
writeln(setA >< setB); |
writeln(setA >< setB); |
||
end func;</ |
end func;</syntaxhighlight> |
||
Output: |
Output: |
||
Line 2,708: | Line 3,555: | ||
{Jim, Serena} |
{Jim, Serena} |
||
</pre> |
</pre> |
||
=={{header|SETL}}== |
|||
<syntaxhighlight lang="setl">program symmetric_difference; |
|||
A := {"John", "Bob", "Mary", "Serena"}; |
|||
B := {"Jim", "Mary", "John", "Bob"}; |
|||
print("A - B:", A - B); |
|||
print("B - A:", B - A); |
|||
print("Symmetric difference:", (A-B) + (B-A)); |
|||
end program;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>A - B: {Serena} |
|||
B - A: {Jim} |
|||
Symmetric difference: {Jim Serena}</pre> |
|||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">var a = ["John", "Serena", "Bob", "Mary", "Serena"]; |
||
var b = ["Jim", "Mary", "John", "Jim", "Bob"]; |
var b = ["Jim", "Mary", "John", "Jim", "Bob"]; |
||
a ^ b -> unique.dump.say;</ |
a ^ b -> unique.dump.say;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,719: | Line 3,580: | ||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
< |
<syntaxhighlight lang="smalltalk">|A B| |
||
A := Set new. |
A := Set new. |
||
B := Set new. |
B := Set new. |
||
Line 2,725: | Line 3,586: | ||
B addAll: #( 'Jim' 'Mary' 'John' 'Bob' ). |
B addAll: #( 'Jim' 'Mary' 'John' 'Bob' ). |
||
( (A - B) + (B - A) ) displayNl.</ |
( (A - B) + (B - A) ) displayNl.</syntaxhighlight> |
||
Output is |
Output is |
||
<pre> |
<pre> |
||
Line 2,732: | Line 3,593: | ||
=={{header|SQL}}/{{header|PostgreSQL}}== |
=={{header|SQL}}/{{header|PostgreSQL}}== |
||
< |
<syntaxhighlight lang="sql">create or replace function arrxor(anyarray,anyarray) returns anyarray as $$ |
||
select ARRAY( |
select ARRAY( |
||
( |
( |
||
Line 2,745: | Line 3,606: | ||
) |
) |
||
) |
) |
||
$$ language sql strict immutable;</ |
$$ language sql strict immutable;</syntaxhighlight> |
||
Usage: |
Usage: |
||
< |
<syntaxhighlight lang="sql">select arrxor('{this,is,a,test}'::text[],'{also,part,of,a,test}'::text[]);</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,758: | Line 3,619: | ||
Swift's <code>Set</code> type supports difference as well as symmetric difference operators. |
Swift's <code>Set</code> type supports difference as well as symmetric difference operators. |
||
{{works with|Swift|1.2+}} |
{{works with|Swift|1.2+}} |
||
< |
<syntaxhighlight lang="swift">let setA : Set<String> = ["John", "Bob", "Mary", "Serena"] |
||
let setB : Set<String> = ["Jim", "Mary", "John", "Bob"] |
let setB : Set<String> = ["Jim", "Mary", "John", "Bob"] |
||
println(setA.exclusiveOr(setB)) // symmetric difference of A and B |
println(setA.exclusiveOr(setB)) // symmetric difference of A and B |
||
println(setA.subtract(setB)) // elements in A that are not in B</ |
println(setA.subtract(setB)) // elements in A that are not in B</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,771: | Line 3,632: | ||
It's common to represent sets as an unordered list of elements. (It is also the most efficient representation.) The <code>struct::set</code> package contains operations for working on such sets-as-lists. |
It's common to represent sets as an unordered list of elements. (It is also the most efficient representation.) The <code>struct::set</code> package contains operations for working on such sets-as-lists. |
||
{{tcllib|struct::set}} |
{{tcllib|struct::set}} |
||
< |
<syntaxhighlight lang="tcl">package require struct::set |
||
set A {John Bob Mary Serena} |
set A {John Bob Mary Serena} |
||
Line 2,785: | Line 3,646: | ||
# Of course, the library already has this operation directly... |
# Of course, the library already has this operation directly... |
||
puts "Direct Check: [struct::set symdiff $A $B]"</ |
puts "Direct Check: [struct::set symdiff $A $B]"</syntaxhighlight> |
||
Produces this output:<pre> |
Produces this output:<pre> |
||
A\B = Serena |
A\B = Serena |
||
Line 2,794: | Line 3,655: | ||
=={{header|TUSCRIPT}}== |
=={{header|TUSCRIPT}}== |
||
< |
<syntaxhighlight lang="tuscript">$$ MODE TUSCRIPT |
||
a="John'Bob'Mary'Serena" |
a="John'Bob'Mary'Serena" |
||
b="Jim'Mary'John'Bob" |
b="Jim'Mary'John'Bob" |
||
Line 2,815: | Line 3,676: | ||
LOOP n=names,v=val |
LOOP n=names,v=val |
||
PRINT n," in: ",v |
PRINT n," in: ",v |
||
ENDLOOP</ |
ENDLOOP</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 2,829: | Line 3,690: | ||
=={{header|UNIX Shell}}== |
=={{header|UNIX Shell}}== |
||
{{works with|Bash}} |
{{works with|Bash}} |
||
< |
<syntaxhighlight lang="bash">uniq() { |
||
u=("$@") |
u=("$@") |
||
for ((i=0;i<${#u[@]};i++)); do |
for ((i=0;i<${#u[@]};i++)); do |
||
Line 2,871: | Line 3,732: | ||
echo "A - B = ${ab[@]}" |
echo "A - B = ${ab[@]}" |
||
echo "B - A = ${ba[@]}" |
echo "B - A = ${ba[@]}" |
||
echo "Symmetric difference = ${sd[@]}"</ |
echo "Symmetric difference = ${sd[@]}"</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>Set A = John Serena Bob Mary Serena |
<pre>Set A = John Serena Bob Mary Serena |
||
Line 2,882: | Line 3,743: | ||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
< |
<syntaxhighlight lang="ursala">a = <'John','Bob','Mary','Serena'> |
||
b = <'Jim','Mary','John','Bob'> |
b = <'Jim','Mary','John','Bob'> |
||
Line 2,894: | Line 3,755: | ||
'a not b': ~&j/a b, |
'a not b': ~&j/a b, |
||
'b not a': ~&j/b a, |
'b not a': ~&j/b a, |
||
'symmetric difference': ~&jrljTs/a b></ |
'symmetric difference': ~&jrljTs/a b></syntaxhighlight> |
||
output: |
output: |
||
<pre>< |
<pre>< |
||
Line 2,902: | Line 3,763: | ||
'b not a': <'Jim'>, |
'b not a': <'Jim'>, |
||
'symmetric difference': <'Jim','Serena'>></pre> |
'symmetric difference': <'Jim','Serena'>></pre> |
||
=={{header|V (Vlang)}}== |
|||
<syntaxhighlight lang="v (vlang)"> |
|||
const |
|||
( |
|||
alist = ["john", "bob", "mary", "serena"] |
|||
blist = ["jim", "mary", "john", "bob"] |
|||
) |
|||
fn main() { |
|||
mut rlist := []string{} |
|||
for elem in alist { |
|||
if blist.any(it == elem) == false { |
|||
println("a - b = $elem") |
|||
rlist << elem |
|||
} |
|||
} |
|||
for elem in blist { |
|||
if alist.any(it == elem) == false { |
|||
println("b - a = $elem") |
|||
rlist << elem |
|||
} |
|||
} |
|||
println("symmetric difference: $rlist") |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
a - b = serena |
|||
b - a = jim |
|||
symmetric difference: ['serena', 'jim'] |
|||
</pre> |
|||
=={{header|Wren}}== |
|||
{{libheader|Wren-set}} |
|||
<syntaxhighlight lang="wren">import "./set" for Set |
|||
var symmetricDifference = Fn.new { |a, b| a.except(b).union(b.except(a)) } |
|||
var a = Set.new(["John", "Bob", "Mary", "Serena"]) |
|||
var b = Set.new(["Jim", "Mary", "John", "Bob"]) |
|||
System.print("A = %(a)") |
|||
System.print("B = %(b)") |
|||
System.print("A - B = %(a.except(b))") |
|||
System.print("B - A = %(b.except(a))") |
|||
System.print("A △ B = %(symmetricDifference.call(a, b))")</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A = <Serena, Bob, Mary, John> |
|||
B = <Jim, Bob, Mary, John> |
|||
A - B = <Serena> |
|||
B - A = <Jim> |
|||
A △ B = <Serena, Jim> |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
An integer in XPL0 can represent a set of up to 32 elements, and bitwise Boolean |
|||
operations can represent union, intersection, and difference. |
|||
<syntaxhighlight lang="xpl0">def John, Bob, Mary, Serena, Jim; \enumerate set items (0..4) |
|||
proc SetOut(S); \Output the elements in set |
|||
int S; |
|||
int Name, I; |
|||
[Name:= ["John", "Bob", "Mary", "Serena", "Jim"]; |
|||
for I:= 0 to 31 do |
|||
if S & 1<<I then |
|||
[Text(0, Name(I)); ChOut(0, ^ )]; |
|||
CrLf(0); |
|||
]; |
|||
int A, B; |
|||
[A:= 1<<John ! 1<<Bob ! 1<<Mary ! 1<<Serena; |
|||
B:= 1<<Jim ! 1<<Mary ! 1<<John ! 1<<Bob; |
|||
Text(0, "A xor B = "); SetOut(A | B); |
|||
Text(0, "A\B = "); SetOut(A & ~B); |
|||
Text(0, "B\A = "); SetOut(B & ~A); |
|||
Text(0, "A\B U B\A = "); SetOut(A&~B ! B&~A); |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A xor B = Serena Jim |
|||
A\B = Serena |
|||
B\A = Jim |
|||
A\B U B\A = Serena Jim |
|||
</pre> |
|||
=={{header|Yabasic}}== |
=={{header|Yabasic}}== |
||
< |
<syntaxhighlight lang="yabasic">lista1$ = "John Serena Bob Mary Serena" |
||
lista2$ = "Jim Mary John Jim Bob" |
lista2$ = "Jim Mary John Jim Bob" |
||
Line 2,948: | Line 3,898: | ||
wend |
wend |
||
end sub |
end sub |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
< |
<syntaxhighlight lang="zkl">fcn setCommon(list1,list2){ list1.filter(list2.holds); } |
||
fcn sdiff(list1,list2) |
fcn sdiff(list1,list2) |
||
{ list1.extend(list2).copy().removeEach(setCommon(list1,list2)) }</ |
{ list1.extend(list2).copy().removeEach(setCommon(list1,list2)) }</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl">a:=T("John","Bob","Mary","Serena"); |
||
b:=T("Jim","Mary","John","Bob"); |
b:=T("Jim","Mary","John","Bob"); |
||
sdiff(a,b).println();</ |
sdiff(a,b).println();</syntaxhighlight> |
||
To deal with duplicates, use [[Remove duplicate elements#zkl]]: |
To deal with duplicates, use [[Remove duplicate elements#zkl]]: |
||
< |
<syntaxhighlight lang="zkl">a:=T("John", "Serena", "Bob", "Mary", "Serena"); |
||
b:=T("Jim", "Mary", "John", "Jim", "Bob"); |
b:=T("Jim", "Mary", "John", "Jim", "Bob"); |
||
sdiff(a,b) : Utils.Helpers.listUnique(_).println();</ |
sdiff(a,b) : Utils.Helpers.listUnique(_).println();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Latest revision as of 18:23, 21 April 2024
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Given two sets A and B, 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.
In other words: (the set of items that are in at least one of A or B minus the set of items that are in both A and B).
Optionally, give the individual differences ( and ) as well.
- Test cases
A = {John, Bob, Mary, Serena} B = {Jim, Mary, John, Bob}
- Notes
- 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"]
andb = ["Jim", "Mary", "John", "Jim", "Bob"]
should produce the result of just two strings:["Serena", "Jim"]
, in any order. - In the mathematical notation above
A \ B
gives the set of items in A that are not in B;A ∪ B
gives the set of items in both A and B, (their union); andA ∩ B
gives the set of items that are in both A and B (their intersection).
11l
V setA = Set([‘John’, ‘Bob’, ‘Mary’, ‘Serena’])
V setB = Set([‘Jim’, ‘Mary’, ‘John’, ‘Bob’])
print(setA.symmetric_difference(setB))
print(setA - setB)
print(setB - setA)
- Output:
Set([Jim, Serena]) Set([Serena]) Set([Jim])
Action!
The user must type in the monitor the following command after compilation and before running the program!
SET EndProg=*
CARD EndProg ;required for ALLOCATE.ACT
INCLUDE "D2:ALLOCATE.ACT" ;from the Action! Tool Kit. You must type 'SET EndProg=*' from the monitor after compiling, but before running this program!
DEFINE PTR="CARD"
DEFINE NODE_SIZE="6"
TYPE SetNode=[PTR data,prv,nxt]
TYPE SetInfo=[PTR name,begin,end]
PROC PrintSet(SetInfo POINTER s)
SetNode POINTER n
CHAR ARRAY a
n=s.begin
PrintF("%S=(",s.name)
WHILE n
DO
Print(n.data)
a=n.data
IF n.nxt THEN
Print(", ")
FI
n=n.nxt
OD
PrintE(")")
RETURN
PROC CreateSet(SetInfo POINTER s CHAR ARRAY n)
s.name=n
s.begin=0
s.end=0
RETURN
PTR FUNC Find(SetInfo POINTER s CHAR ARRAY v)
SetNode POINTER n
n=s.begin
WHILE n
DO
IF SCompare(v,n.data)=0 THEN
RETURN (n)
FI
n=n.nxt
OD
RETURN (0)
BYTE FUNC Contains(SetInfo POINTER s CHAR ARRAY v)
SetNode POINTER n
n=Find(s,v)
IF n=0 THEN
RETURN (0)
FI
RETURN (1)
PROC Append(SetInfo POINTER s CHAR ARRAY v)
SetNode POINTER n,tmp
IF Contains(s,v) THEN RETURN FI
n=Alloc(NODE_SIZE)
n.data=v
n.prv=s.end
n.nxt=0
IF s.end THEN
tmp=s.end tmp.nxt=n
ELSE
s.begin=n
FI
s.end=n
RETURN
PROC Remove(SetInfo POINTER s CHAR ARRAY v)
SetNode POINTER n,prev,next
n=Find(s,v)
IF n=0 THEN RETURN FI
prev=n.prv
next=n.nxt
Free(n,NODE_SIZE)
IF prev THEN
prev.nxt=next
ELSE
s.begin=next
FI
IF next THEN
next.prv=prev
ELSE
s.end=prev
FI
RETURN
PROC AppendSet(SetInfo POINTER s,other)
SetNode POINTER n
n=other.begin
WHILE n
DO
Append(s,n.data)
n=n.nxt
OD
RETURN
PROC RemoveSet(SetInfo POINTER s,other)
SetNode POINTER n
n=other.begin
WHILE n
DO
Remove(s,n.data)
n=n.nxt
OD
RETURN
PROC Clear(SetInfo POINTER s)
SetNode POINTER n
DO
n=s.begin
IF n=0 THEN RETURN FI
Remove(s,n.data)
OD
RETURN
PROC Union(SetInfo POINTER a,b,res)
Clear(res)
AppendSet(res,a)
AppendSet(res,b)
RETURN
PROC Difference(SetInfo POINTER a,b,res)
Clear(res)
AppendSet(res,a)
RemoveSet(res,b)
RETURN
PROC SymmetricDifference(SetInfo POINTER a,b,res)
SetInfo tmp1,tmp2
CreateSet(tmp1,"")
CreateSet(tmp2,"")
Difference(a,b,tmp1)
Difference(b,a,tmp2)
Union(tmp1,tmp2,res)
Clear(tmp1)
Clear(tmp2)
RETURN
PROC TestSymmetricDifference(SetInfo POINTER a,b,res)
SymmetricDifference(a,b,res)
PrintF("%S XOR %S: ",a.name,b.name)
PrintSet(res)
RETURN
PROC TestDifference(SetInfo POINTER a,b,res)
Difference(a,b,res)
PrintF("%S-%S: ",a.name,b.name)
PrintSet(res)
RETURN
PROC Main()
SetInfo s1,s2,s3
Put(125) PutE() ;clear screen
AllocInit(0)
CreateSet(s1,"A")
CreateSet(s2,"B")
CreateSet(s3,"C")
Append(s1,"John") Append(s1,"Bob")
Append(s1,"Mary") Append(s1,"Serena")
Append(s2,"Jim") Append(s2,"Mary")
Append(s2,"John") Append(s2,"Bob")
PrintSet(s1) PrintSet(s2)
PutE()
TestSymmetricDifference(s1,s2,s3)
TestDifference(s1,s2,s3)
TestDifference(s2,s1,s3)
Clear(s1)
Clear(s2)
Clear(s3)
RETURN
- Output:
Screenshot from Atari 8-bit computer
A=(John, Bob, Mary, Serena) B=(Jim, Mary, John, Bob) A XOR B: C=(Serena, Jim) A-B: C=(Serena) B-A: C=(Jim)
Ada
Ada has the lattice operation xor predefined on Boolean, modular types, 1D arrays, set implementations from the standard library. The provided solution 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
Aime
show_sdiff(record u, x)
{
record r;
text s;
r.copy(u);
for (s in x) {
if (r.key(s)) {
r.delete(s);
} else {
r.p_integer(s, 0);
}
}
r.vcall(o_, 0, "\n");
}
new_set(...)
{
record r;
ucall(r_p_integer, 1, r, 0);
r;
}
main(void)
{
show_sdiff(new_set("John", "Bob", "Mary", "Serena"),
new_set("Jim", "Mary", "John", "Bob"));
0;
}
- Output:
Jim Serena
ALGOL 68
Uses the associative array implementations in ALGOL_68/prelude.
# symetric difference using associative arrays to represent the sets #
# include the associative array code for string keys and values #
PR read "aArray.a68" PR
# adds the elements of s to the associative array a, #
# the elements will have empty strings for values #
OP // = ( REF AARRAY a, []STRING s )REF AARRAY:
BEGIN
FOR s pos FROM LWB s TO UPB s DO
a // s[ s pos ] := ""
OD;
a
END # // # ;
# returns an AARRAY containing the elements of a that aren't in b #
OP - = ( REF AARRAY a, REF AARRAY b )REF AARRAY:
BEGIN
REF AARRAY result := INIT HEAP AARRAY;
REF AAELEMENT e := FIRST a;
WHILE e ISNT nil element DO
IF NOT ( b CONTAINSKEY key OF e ) THEN
result // key OF e := value OF e
FI;
e := NEXT a
OD;
result
END # - # ;
# returns an AARRAY containing the elements of a and those of b #
# i.e. in set terms a UNION b #
OP + = ( REF AARRAY a, REF AARRAY b )REF AARRAY:
BEGIN
REF AARRAY result := INIT HEAP AARRAY;
REF AAELEMENT e := FIRST a;
WHILE e ISNT nil element DO
result // key OF e := value OF e;
e := NEXT a
OD;
e := FIRST b;
WHILE e ISNT nil element DO
result // key OF e := value OF e;
e := NEXT b
OD;
result
END # + # ;
# construct the associative arrays for the task #
REF AARRAY a := INIT LOC AARRAY;
REF AARRAY b := INIT LOC AARRAY;
a // []STRING( "John", "Bob", "Mary", "Serena" );
b // []STRING( "Jim", "Mary", "John", "Bob" );
# find and show the symetric difference of a and b #
REF AARRAY c := ( a - b ) + ( b - a );
REF AAELEMENT e := FIRST c;
WHILE e ISNT nil element DO
print( ( " ", key OF e ) );
e := NEXT c
OD;
print( ( newline ) )
- Output:
Serena Jim
Amazing Hopper
#include <basico.h>
algoritmo
matrices (A, B)
"John", "Bob", "Mary", "Serena", enlistar en 'A'
"Jim", "Mary", "John", "Bob", enlistar en 'B'
" A XOR B: {", diferencia simétrica(A,B), "}\n"
" A \ B: {", diferencia(A,B), "}\n"
" B \ A: {", diferencia(B,A), "}\n"
imprimir
terminar
- Output:
A XOR B: {Jim,Serena} A \ B: {Serena} B \ A: {Jim}
Apex
Set<String> setA = new Set<String>{'John', 'Bob', 'Mary', 'Serena'};
Set<String> setB = new Set<String>{'Jim', 'Mary', 'John', 'Bob'};
// Option 1
Set<String> notInSetA = setB.clone();
notInSetA.removeAll(setA);
Set<String> notInSetB = setA.clone();
notInSetB.removeAll(setB);
Set<String> symmetricDifference = new Set<String>();
symmetricDifference.addAll(notInSetA);
symmetricDifference.addAll(notInSetB);
// Option 2
Set<String> union = setA.clone();
union.addAll(setB);
Set<String> intersection = setA.clone();
intersection.retainAll(setB);
Set<String> symmetricDifference2 = union.clone();
symmetricDifference2.removeAll(intersection);
System.debug('Not in set A: ' + notInSetA);
System.debug('Not in set B: ' + notInSetB);
System.debug('Symmetric Difference: ' + symmetricDifference);
System.debug('Symmetric Difference 2: ' + symmetricDifference2);
- Output:
Not in set A: {Jim} Not in set B: {Serena} Symmetric Difference: {Jim, Serena} Symmetric Difference 2: {Jim, Serena}
APL
symdiff ← ∪~∩
- Output:
'John' 'Bob' 'Mary' 'Serena' symdiff 'Jim' 'Mary' 'John' 'Bob' Serena Jim
AppleScript
Functional
(ES6 Functional JS)
-- SYMMETRIC DIFFERENCE -------------------------------------------
-- symmetricDifference :: [a] -> [a] -> [a]
on symmetricDifference(xs, ys)
union(difference(xs, ys), difference(ys, xs))
end symmetricDifference
-- TEST -----------------------------------------------------------
on run
set a to ["John", "Serena", "Bob", "Mary", "Serena"]
set b to ["Jim", "Mary", "John", "Jim", "Bob"]
symmetricDifference(a, b)
--> {"Serena", "Jim"}
end run
-- GENERIC FUNCTIONS ----------------------------------------------
-- delete :: Eq a => a -> [a] -> [a]
on |delete|(x, xs)
set mbIndex to elemIndex(x, xs)
set lng to length of xs
if mbIndex is not missing value then
if lng > 1 then
if mbIndex = 1 then
items 2 thru -1 of xs
else if mbIndex = lng then
items 1 thru -2 of xs
else
tell xs to items 1 thru (mbIndex - 1) & ¬
items (mbIndex + 1) thru -1
end if
else
{}
end if
else
xs
end if
end |delete|
-- difference :: [a] -> [a] -> [a]
on difference(xs, ys)
script
on |λ|(a, y)
if a contains y then
my |delete|(y, a)
else
a
end if
end |λ|
end script
foldl(result, xs, ys)
end difference
-- elemIndex :: a -> [a] -> Maybe Int
on elemIndex(x, xs)
set lng to length of xs
repeat with i from 1 to lng
if x = (item i of xs) then return i
end repeat
return missing value
end elemIndex
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- nub :: [a] -> [a]
on nub(xs)
if (length of xs) > 1 then
set x to item 1 of xs
[x] & nub(|delete|(x, items 2 thru -1 of xs))
else
xs
end if
end nub
-- union :: [a] -> [a] -> [a]
on union(xs, ys)
script flipDelete
on |λ|(xs, x)
my |delete|(x, xs)
end |λ|
end script
set sx to nub(xs)
sx & foldl(flipDelete, nub(ys), sx)
end union
- Output:
{"Serena", "Jim"}
Some alternatives
There are several ways to approach this problem. Vanilla AppleScript doesn't do sets, but the following returns the required results:
on symmetricDifference(a, b)
set output to {}
repeat 2 times
repeat with thisItem in a
set thisItem to thisItem's contents
tell {thisItem}
if (not ((it is in b) or (it is in output))) then set end of output to thisItem
end tell
end repeat
set {a, b} to {b, a}
end repeat
return output
end symmetricDifference
on task()
set a to {"John", "Serena", "Bob", "Mary", "Serena"}
set b to {"Jim", "Mary", "John", "Jim", "Bob"}
return symmetricDifference(a, b)
end task
task()
- Output:
{"Serena", "Jim"}
AppleScriptObjC gives access to the Foundation framework's NSSet classes, whose mutable variety has relevant methods. A symmetricDifference() handler implementing (A ∖ B) ∪ (B ∖ A) might be:
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
on symmetricDifference(a, b)
set a to current application's class "NSSet"'s setWithArray:(a)
set b to current application's class "NSMutableSet"'s setWithArray:(b)
set output to a's mutableCopy()
tell output to minusSet:(b)
tell b to minusSet:(a)
tell output to unionSet:(b)
return output's allObjects() as list
end symmetricDifference
And for (A ∪ B) ∖ (A ∩ B):
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
on symmetricDifference(a, b)
set a to current application's class "NSSet"'s setWithArray:(a)
set b to current application's class "NSMutableSet"'s setWithArray:(b)
set output to a's mutableCopy()
tell output to unionSet:(b)
tell b to intersectSet:(a)
tell output to minusSet:(b)
return output's allObjects() as list
end symmetricDifference
It's also possible in ASObjC to filter arrays or sets if you're so inclined:
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
on symmetricDifference(a, b)
set unionArray to (current application's class "NSArray"'s arrayWithArray:({a, b}))'s ¬
valueForKeyPath:("@distinctUnionOfArrays.self")
set filter to current application's class "NSPredicate"'s ¬
predicateWithFormat_("!((self IN %@) && (self IN %@))", a, b)
return (unionArray's filteredArrayUsingPredicate:(filter)) as list
end symmetricDifference
Arturo
a: ["John" "Bob" "Mary" "Serena"]
b: ["Jim" "Mary" "John" "Bob"]
print difference.symmetric a b
- Output:
Serena Jim
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
AWK
# syntax: GAWK -f SYMMETRIC_DIFFERENCE.AWK
BEGIN {
load("John,Bob,Mary,Serena",A)
load("Jim,Mary,John,Bob",B)
show("A \\ B",A,B)
show("B \\ A",B,A)
printf("symmetric difference: ")
for (i in C) {
if (!(i in A && i in B)) {
printf("%s ",i)
}
}
printf("\n")
exit(0)
}
function load(str,arr, i,n,temp) {
n = split(str,temp,",")
for (i=1; i<=n; i++) {
arr[temp[i]]
C[temp[i]]
}
}
function show(str,a,b, i) {
printf("%s: ",str)
for (i in a) {
if (!(i in b)) {
printf("%s ",i)
}
}
printf("\n")
}
output:
A \ B: Serena B \ A: Jim symmetric difference: Serena Jim
BBC BASIC
Here sets are represented as integers, hence there are a maximum of 32 elements in a set.
DIM list$(4)
list$() = "Bob", "Jim", "John", "Mary", "Serena"
setA% = %11101
PRINT "Set A: " FNlistset(list$(), setA%)
setB% = %01111
PRINT "Set B: " FNlistset(list$(), setB%)
REM Compute symmetric difference:
setC% = setA% EOR setB%
PRINT '"Symmetric difference: " FNlistset(list$(), setC%)
REM Optional:
PRINT "Set A \ Set B: " FNlistset(list$(), setA% AND NOT setB%)
PRINT "Set B \ Set A: " FNlistset(list$(), setB% AND NOT setA%)
END
DEF FNlistset(list$(), set%)
LOCAL i%, o$
FOR i% = 0 TO 31
IF set% AND 1 << i% o$ += list$(i%) + ", "
NEXT
= LEFT$(LEFT$(o$))
Output:
Set A: Bob, John, Mary, Serena Set B: Bob, Jim, John, Mary Symmetric difference: Jim, Serena Set A \ Set B: Serena Set B \ Set A: Jim
Bracmat
Walk through the concatenation of the two lists, using backtracking (forced by the ~ operator).
If an element is in both lists, or if the element already is in the accumulated result symdiff
, continue. Otherwise add the element to symdiff
. When all elements are done and backtracking therefore finally fails, return the contents of symdiff
. The flag %
in the pattern %@?x
ensures that only nontrivial elements (i.e. non-empty strings in this case) are matched. The @
flag ensures that at most one string is matched. Together these flags ensure that exactly one element is matched.
(SymmetricDifference=
A B x symdiff
. !arg:(?A.?B)
& :?symdiff
& ( !A !B
: ?
( %@?x
& ( !A:? !x ?&!B:? !x ?
| !symdiff:? !x ?
| !symdiff !x:?symdiff
)
& ~
)
?
| !symdiff
));
Run:
SymmetricDifference$(john serena bob mary serena.jim mary john jim bob)
Output:
serena jim
C
Simple method:
#include <stdio.h>
#include <string.h>
const char *A[] = { "John", "Serena", "Bob", "Mary", "Serena" };
const char *B[] = { "Jim", "Mary", "John", "Jim", "Bob" };
#define LEN(x) sizeof(x)/sizeof(x[0])
/* null duplicate items */
void uniq(const char *x[], int len)
{
int i, j;
for (i = 0; i < len; i++)
for (j = i + 1; j < len; j++)
if (x[j] && x[i] && !strcmp(x[i], x[j])) x[j] = 0;
}
int in_set(const char *const x[], int len, const char *match)
{
int i;
for (i = 0; i < len; i++)
if (x[i] && !strcmp(x[i], match))
return 1;
return 0;
}
/* x - y */
void show_diff(const char *const x[], int lenx, const char *const y[], int leny)
{
int i;
for (i = 0; i < lenx; i++)
if (x[i] && !in_set(y, leny, x[i]))
printf(" %s\n", x[i]);
}
/* X ^ Y */
void show_sym_diff(const char *const x[], int lenx, const char *const y[], int leny)
{
show_diff(x, lenx, y, leny);
show_diff(y, leny, x, lenx);
}
int main()
{
uniq(A, LEN(A));
uniq(B, LEN(B));
printf("A \\ B:\n"); show_diff(A, LEN(A), B, LEN(B));
printf("\nB \\ A:\n"); show_diff(B, LEN(B), A, LEN(A));
printf("\nA ^ B:\n"); show_sym_diff(A, LEN(A), B, LEN(B));
return 0;
}
output
A \ B: Serena B \ A: Jim A ^ B: Serena Jim
If you prefer something elaborate:
#include <assert.h>
#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;
}
/* isSet tests that elements of list are unique, that is, that the list is a
* mathematical set. The uniqueness test implemented here is strcmp. */
int isSet(const char *list[], int lsize)
{
int i, j;
const char *e;
if (lsize == 0) {
return 1;
}
for (i = lsize-1; i>0; i--) {
e = list[i];
for (j = i-1; j>=0; j--) {
if (strcmp(list[j], e) == 0) {
return 0;
}
}
}
return 1;
}
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;
/* Validate precondition stated by task, that inputs are sets. */
assert(isSet(XSET(setA)));
assert(isSet(XSET(setB)));
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 }
C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace RosettaCode.SymmetricDifference
{
public static class IEnumerableExtension
{
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> @this, IEnumerable<T> that)
{
return @this.Except(that).Concat(that.Except(@this));
}
}
class Program
{
static void Main()
{
var a = new[] { "John", "Bob", "Mary", "Serena" };
var b = new[] { "Jim", "Mary", "John", "Bob" };
foreach (var element in a.SymmetricDifference(b))
{
Console.WriteLine(element);
}
}
}
}
Output:
Serena Jim
C++
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
#include <string>
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.end() ) );
copy( symdiff.begin(), symdiff.end(), ostream_iterator<string>( cout , " " ) );
cout << endl;
return 0;
}
Output: Jim Serena
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})
Common Lisp
(set-exclusive-or
(remove-duplicates '(John Serena Bob Mary Serena))
(remove-duplicates '(Jim Mary John Jim Bob)))
Output:
(JIM SERENA)
D
Generic version.
import std.stdio, std.algorithm, std.array;
struct Set(T) {
immutable T[] items;
Set opSub(in Set other) const pure nothrow {
return items.filter!(x => !other.items.canFind(x)).array.Set;
}
Set opAdd(in Set other) const pure nothrow {
return Set(this.items ~ (other - this).items);
}
}
Set!T symmetricDifference(T)(in Set!T left, in Set!T right)
pure nothrow {
return (left - right) + (right - left);
}
void main() {
immutable A = ["John", "Bob", "Mary", "Serena"].Set!string;
immutable B = ["Jim", "Mary", "John", "Bob"].Set!string;
writeln(" A\\B: ", (A - B).items);
writeln(" B\\A: ", (B - A).items);
writeln("A symdiff B: ", symmetricDifference(A, B).items);
}
- Output:
A\B: ["Serena"] B\A: ["Jim"] A symdiff B: ["Serena", "Jim"]
Datalog
Implemented using Souffle.
.decl A(text: symbol)
.decl B(text: symbol)
.decl SymmetricDifference(text: symbol)
.output SymmetricDifference
A("this").
A("is").
A("a").
A("test").
B("also").
B("part").
B("of").
B("a").
B("test").
SymmetricDifference(x) :- A(x), !B(x).
SymmetricDifference(x) :- B(x), !A(x).
- Output:
this is also part of
Delphi
Small variation of pascal.
PROGRAM Symmetric_difference;
uses
System.Typinfo;
TYPE
TName = (Bob, Jim, John, Mary, Serena);
TList = SET OF TName;
TNameHelper = record helper for TName
FUNCTION ToString(): string;
end;
{ TNameHlper }
FUNCTION TNameHelper.ToString: string;
BEGIN
Result := GetEnumName(TypeInfo(TName), Ord(self));
END;
PROCEDURE Put(txt: String; ResSet: TList);
VAR
I: TName;
BEGIN
Write(txt);
FOR I IN ResSet DO
Write(I.ToString, ' ');
WriteLn;
END;
VAR
ListA: TList = [John, Bob, Mary, Serena];
ListB: TList = [Jim, Mary, John, Bob];
BEGIN
Put('ListA -> ', ListA);
Put('ListB -> ', ListB);
Put('ListA >< ListB -> ', (ListA - ListB) + (ListB - ListA));
Put('ListA - ListB -> ', ListA - ListB);
Put('ListB - ListA -> ', ListB - ListA);
ReadLn;
END.
Delphi/Object Pascal actually has a 'Symmetric Difference' operator `> <`:
program SymmetricDifference;
type
charSet = set of Char;
var
s1, s2, s3: charSet;
ch: char;
begin
s1 := ['a', 'b', 'c', 'd'];
s2 := ['c', 'd', 'e', 'f'];
s3 := s1 >< s2;
for ch in s3 do
write(ch, ' ');
writeLn;
end.
Output:
a b e f
Déjà Vu
Déjà Vu has no real set type. Instead, it uses a dictionary whose keys are the set values. The set{
constructor uses true
as a dummy value, and sets false
as a dummy value.
set :setA set{ :John :Bob :Mary :Serena }
set :setB set{ :Jim :Mary :John :Bob }
symmetric-difference A B:
}
for a in keys A:
if not has B a:
a
for b in keys B:
if not has A b:
b
set{
!. symmetric-difference setA setB
- Output:
set{ :Serena :Jim }
E
? def symmDiff(a, b) { return (a &! b) | (b &! a) }
# value: <symmDiff>
? symmDiff(["John", "Bob", "Mary", "Serena"].asSet(), ["Jim", "Mary", "John", "Bob"].asSet())
# value: ["Jim", "Serena"].asSet()
EasyLang
a$[] = [ "John" "Bob" "Mary" "Serena" ]
b$[] = [ "Jim" "Mary" "John" "Bob" ]
#
for i to 2
for a$ in a$[]
for b$ in b$[]
if a$ = b$
a$ = ""
break 1
.
.
if a$ <> ""
c$[] &= a$
.
.
swap a$[] b$[]
.
print c$[]
Eiffel
note
description: "Summary description for {SYMETRIC_DIFFERENCE_EXAMPLE}."
URI: "http://rosettacode.org/wiki/Symmetric_difference"
class
SYMETRIC_DIFFERENCE_EXAMPLE
create
make
feature {NONE} -- Initialization
make
local
a,a1,b,b1: ARRAYED_SET [STRING]
do
create a.make (4)
create b.make (4)
a.compare_objects
b.compare_objects
a.put ("John")
a.put ("Bob")
a.put ("Mary")
a.put ("Serena")
create a1.make (4)
a1.copy (a)
b.put ("Jim")
b.put ("Mary")
b.put ("John")
b.put ("Bob")
create b1.make (4)
b1.copy (b)
a1.subtract (b1)
b.subtract (a)
a1.merge (b)
across a1 as c loop
print (" " + c.item)
end
end
end
Elixir
iex(1)> a = ~w[John Bob Mary Serena] |> MapSet.new
#MapSet<["Bob", "John", "Mary", "Serena"]>
iex(2)> b = ~w[Jim Mary John Bob] |> MapSet.new
#MapSet<["Bob", "Jim", "John", "Mary"]>
iex(3)> sym_dif = fn(a,b) -> MapSet.difference(MapSet.union(a,b), MapSet.intersection(a,b)) end
#Function<12.54118792/2 in :erl_eval.expr/5>
iex(4)> sym_dif.(a,b)
#MapSet<["Jim", "Serena"]>
Erlang
%% Implemented by Arjun Sunel
-module(symdiff).
-export([main/0]).
main() ->
SetA = sets:from_list(["John","Bob","Mary","Serena"]),
SetB = sets:from_list(["Jim","Mary","John","Bob"]),
AUnionB = sets:union(SetA,SetB),
AIntersectionB = sets:intersection(SetA,SetB),
SymmDiffAB = sets:subtract(AUnionB,AIntersectionB),
sets:to_list(SymmDiffAB).
- Output:
["Serena","Jim"]
F#
> let a = set ["John"; "Bob"; "Mary"; "Serena"]
let b = set ["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"]
Factor
: symmetric-diff ( a b -- c )
[ diff ] [ swap diff ] 2bi append ;
{ "John" "Bob" "Mary" "Serena" } { "Jim" "Mary" "John" "Bob" } symmetric-diff .
Forth
GForth 0.7.0 tested.
: elm ( n -- ; one cell per set )
[ cell 8 * 1- ] literal umin CREATE 1 swap lshift ,
DOES> ( -- 2^n ) @ ;
: universe ( u "name" -- )
dup 0 DO I elm latest swap LOOP
CREATE dup , 0 DO , LOOP
DOES> ( n a -- ) dup @ tuck cells +
swap 0
DO ( n a' )
over I rshift 1 AND
IF dup @ name>string space type THEN
1 cells -
LOOP 2drop ;
5 universe john bob mary serena jim persons
john bob mary serena or or or
jim mary john bob or or or
2dup xor persons
2dup -1 xor and cr persons
swap -1 xor and cr persons
cr bye
Output:
$ gforth wrk.fs serena jim serena jim $
Fortran
program Symmetric_difference
implicit none
character(6) :: a(4) = (/ "John ", "Bob ", "Mary ", "Serena" /)
character(6) :: b(4) = (/ "Jim ", "Mary ", "John ", "Bob " /)
integer :: i, j
outer1: do i = 1, size(a)
do j = 1, i-1
if(a(i) == a(j)) cycle outer1 ! Do not check duplicate items
end do
if(.not. any(b == a(i))) write(*,*) a(i)
end do outer1
outer2: do i = 1, size(b)
do j = 1, i-1
if(b(i) == b(j)) cycle outer2 ! Do not check duplicate items
end do
if(.not. any(a == b(i))) write(*,*) b(i)
end do outer2
end program
Output
Serena Jim
FreeBASIC
redim shared as string Result(-1) 'represent our sets as strings;
'this'll do to illustrate the concept
sub sym( A() as string, B() as string )
dim as integer ai, bi, ri
dim as boolean add_it
for ai = lbound(A) to ubound(A)
add_it = true
for bi = lbound(B) to ubound(B)
if A(ai) = B(bi) then
add_it=false
exit for 'if item is common to both lists, don't include it
end if
next bi
if add_it then
for ri = 0 to ubound(Result)
if A(ai) = Result(ri) then
add_it=false
exit for
'if item is already in the result, don't include it again
end if
next ri
end if
if add_it then
redim preserve as string Result(0 to ubound(Result)+1)
Result(ubound(Result)) = A(ai)
end if
next ai
end sub
dim as string A(0 to 3) = {"John", "Bob", "Mary", "Serena"}
dim as string B(0 to 4) = {"Jim", "Mary", "John", "Bob", "Jim"}
'contains a double to show code can handle it
sym(A(), B())
sym(B(), A())
for i as uinteger = 0 to ubound(Result)
print Result(i)
next i
- Output:
SerenaJim
Frink
A = new set["John", "Bob", "Mary", "Serena"]
B = new set["Jim", "Mary", "John", "Bob"]
println["Symmetric difference: " + symmetricDifference[A,B]]
println["A - B : " + setDifference[A,B]]
println["B - A : " + setDifference[B,A]]
- Output:
Symmetric difference: [Jim, Serena] A - B : [Serena] B - A : [Jim]
FutureBasic
include "NSLog.incl"
local fn SymmetricDifferenceOfSets( setA as CFSetRef, setB as CFSetRef ) as CFSetRef
CFMutableSetRef notInSetA = fn MutableSetWithSet( setB )
MutableSetMinusSet( notInSetA, setA )
CFMutableSetRef notInSetB = fn MutableSetWithSet( setA )
MutableSetMinusSet( notInSetB, setB )
CFMutableSetRef symmetricDifference = fn MutableSetWithSet( notInSetA )
MutableSetUnionSet( symmetricDifference, notInSetB )
end fn = fn SetWithSet( symmetricDifference )
CFSetRef set1, set2
set1 = fn SetWithObjects( @"John", @"Serena", @"Bob", @"Mary", @"Serena", NULL )
set2 = fn SetWithObjects( @"Jim", @"Mary", @"John", @"Jim", @"Bob", NULL )
NSLog( @"Symmetric difference:\n%@", fn SymmetricDifferenceOfSets( set1, set2 ) )
HandleEvents
- Output:
Symmetric difference: {( Jim, Serena )}
GAP
SymmetricDifference := function(a, b)
return Union(Difference(a, b), Difference(b, a));
end;
a := ["John", "Serena", "Bob", "Mary", "Serena"];
b := ["Jim", "Mary", "John", "Jim", "Bob"];
SymmetricDifference(a,b);
[ "Jim", "Serena" ]
Go
package main
import "fmt"
var a = map[string]bool{"John": true, "Bob": true, "Mary": true, "Serena": true}
var b = map[string]bool{"Jim": true, "Mary": true, "John": true, "Bob": true}
func main() {
sd := make(map[string]bool)
for e := range a {
if !b[e] {
sd[e] = true
}
}
for e := range b {
if !a[e] {
sd[e] = true
}
}
fmt.Println(sd)
}
Output:
map[Jim:true Serena:true]
Alternatively, the following computes destructively on a. The result is the same.
func main() {
for e := range b {
delete(a, e)
}
fmt.Println(a)
}
Groovy
Solution:
def symDiff = { Set s1, Set s2 ->
assert s1 != null
assert s2 != null
(s1 + s2) - (s1.intersect(s2))
}
Test:
Set a = ['John', 'Serena', 'Bob', 'Mary', 'Serena']
Set b = ['Jim', 'Mary', 'John', 'Jim', 'Bob']
assert a.size() == 4
assert a == (['Bob', 'John', 'Mary', 'Serena'] as Set)
assert b.size() == 4
assert b == (['Bob', 'Jim', 'John', 'Mary'] as Set)
def aa = symDiff(a, a)
def ab = symDiff(a, b)
def ba = symDiff(b, a)
def bb = symDiff(b, b)
assert aa.empty
assert bb.empty
assert ab == ba
assert ab == (['Jim', 'Serena'] as Set)
assert ab == (['Serena', 'Jim'] as Set)
println """
a: ${a}
b: ${b}
Symmetric Differences
=====================
a <> a: ${aa}
a <> b: ${ab}
b <> a: ${ba}
b <> b: ${bb}
"""
Set apostles = ['Matthew', 'Mark', 'Luke', 'John', 'Peter', 'Paul', 'Silas']
Set beatles = ['John', 'Paul', 'George', 'Ringo', 'Peter', 'Stuart']
Set csny = ['Crosby', 'Stills', 'Nash', 'Young']
Set ppm = ['Peter', 'Paul', 'Mary']
def AA = symDiff(apostles, apostles)
def AB = symDiff(apostles, beatles)
def AC = symDiff(apostles, csny)
def AP = symDiff(apostles, ppm)
def BA = symDiff(beatles, apostles)
def BB = symDiff(beatles, beatles)
def BC = symDiff(beatles, csny)
def BP = symDiff(beatles, ppm)
def CA = symDiff(csny, apostles)
def CB = symDiff(csny, beatles)
def CC = symDiff(csny, csny)
def CP = symDiff(csny, ppm)
def PA = symDiff(ppm, apostles)
def PB = symDiff(ppm, beatles)
def PC = symDiff(ppm, csny)
def PP = symDiff(ppm, ppm)
assert AB == BA
assert AC == CA
assert AP == PA
assert BC == CB
assert BP == PB
assert CP == PC
println """
apostles: ${apostles}
beatles: ${beatles}
csny: ${csny}
ppm: ${ppm}
Symmetric Differences
=====================
apostles <> apostles: ${AA}
apostles <> beatles: ${AB}
apostles <> csny: ${AC}
apostles <> ppm: ${AP}
beatles <> apostles: ${BA}
beatles <> beatles: ${BB}
beatles <> csny: ${BC}
beatles <> ppm: ${BP}
csny <> apostles: ${CA}
csny <> beatles: ${CB}
csny <> csny: ${CC}
csny <> ppm: ${CP}
ppm <> apostles: ${PA}
ppm <> beatles: ${PB}
ppm <> csny: ${PC}
ppm <> ppm: ${PP}
"""
Output:
a: [Mary, Bob, Serena, John] b: [Mary, Bob, Jim, John] Symmetric Differences ===================== a <> a: [] a <> b: [Jim, Serena] b <> a: [Jim, Serena] b <> b: [] apostles: [Paul, Mark, Silas, Peter, Luke, John, Matthew] beatles: [Paul, Stuart, Ringo, Peter, John, George] csny: [Crosby, Young, Nash, Stills] ppm: [Paul, Mary, Peter] Symmetric Differences ===================== apostles <> apostles: [] apostles <> beatles: [Mark, Silas, Stuart, Ringo, Luke, Matthew, George] apostles <> csny: [Paul, Crosby, Mark, Silas, Young, Peter, Luke, John, Matthew, Nash, Stills] apostles <> ppm: [Mark, Mary, Silas, Luke, John, Matthew] beatles <> apostles: [Mark, Stuart, Ringo, Silas, Luke, Matthew, George] beatles <> beatles: [] beatles <> csny: [Paul, Crosby, Stuart, Ringo, Young, Peter, John, Nash, Stills, George] beatles <> ppm: [Mary, Stuart, Ringo, John, George] csny <> apostles: [Paul, Crosby, Mark, Silas, Young, Peter, Luke, John, Nash, Stills, Matthew] csny <> beatles: [Paul, Crosby, Stuart, Ringo, Young, Peter, John, Nash, Stills, George] csny <> csny: [] csny <> ppm: [Paul, Crosby, Mary, Young, Peter, Nash, Stills] ppm <> apostles: [Mark, Mary, Silas, Luke, John, Matthew] ppm <> beatles: [Mary, Stuart, Ringo, John, George] ppm <> csny: [Paul, Crosby, Mary, Young, Peter, Nash, Stills] ppm <> ppm: []
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"]
HicEst
CALL SymmDiff("John,Serena,Bob,Mary,Serena,", "Jim,Mary,John,Jim,Bob,")
CALL SymmDiff("John,Bob,Mary,Serena,", "Jim,Mary,John,Bob,")
SUBROUTINE SymmDiff(set1, set2)
CHARACTER set1, set2, answer*50
answer = " "
CALL setA_setB( set1, set2, answer )
CALL setA_setB( set2, set1, answer )
WRITE(Messagebox,Name) answer ! answer = "Serena,Jim," in both cases
END
SUBROUTINE setA_setB( set1, set2, differences )
CHARACTER set1, set2, differences, a*100
a = set1
EDIT(Text=a, $inLeXicon=set2) ! eg a <= $John,Serena,$Bob,$Mary,Serena,
EDIT(Text=a, Right="$", Mark1, Right=",", Mark2, Delete, DO) ! Serena,Serena,
EDIT(Text=a, Option=1, SortDelDbls=a) ! Option=1: keep case; Serena,
differences = TRIM( differences ) // a
END
Icon and Unicon
Set operations are built into Icon/Unicon.
Sample output:
a = { Serena Mary Bob John } b = { Mary Bob Jim John } (a\b) ∩ (b\a) = { Serena Jim } (a\b) = { Serena } (b\a) = { Jim }
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│
└──────┴───┘
To illustrate some of the underlying mechanics used here:
A -. B NB. items in A but not in B
┌──────┐
│Serena│
└──────┘
A -.~ B NB. items in B but not in A
┌───┐
│Jim│
└───┘
A NB. A is a sequence without duplicates
┌────┬──────┬───┬────┐
│John│Serena│Bob│Mary│
└────┴──────┴───┴────┘
Here's an alternative implementation:
A (, -. [ -. -.) B
┌──────┬───┐
│Serena│Jim│
└──────┴───┘
Here, (,)
contains all items from A and B and ([ -. -.)
is the idiom for set intersection, and their difference is the symmetric difference. (Note: an individual word in a J sentence may be placed inside a parenthesis with no change in evaluation, and this can also be used for emphasis when a word might get lost.)
Java
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class SymmetricDifference {
public static void main(String[] args) {
Set<String> setA = new HashSet<String>(Arrays.asList("John", "Serena", "Bob", "Mary", "Serena"));
Set<String> setB = new HashSet<String>(Arrays.asList("Jim", "Mary", "John", "Jim", "Bob"));
// Present our initial data set
System.out.println("In set A: " + setA);
System.out.println("In set B: " + setB);
// Option 1: union of differences
// Get our individual differences.
Set<String> notInSetA = new HashSet<String>(setB);
notInSetA.removeAll(setA);
Set<String> notInSetB = new HashSet<String>(setA);
notInSetB.removeAll(setB);
// The symmetric difference is the concatenation of the two individual differences
Set<String> symmetricDifference = new HashSet<String>(notInSetA);
symmetricDifference.addAll(notInSetB);
// Option 2: union minus intersection
// Combine both sets
Set<String> union = new HashSet<String>(setA);
union.addAll(setB);
// Get the intersection
Set<String> intersection = new HashSet<String>(setA);
intersection.retainAll(setB);
// The symmetric difference is the union of the 2 sets minus the intersection
Set<String> symmetricDifference2 = new HashSet<String>(union);
symmetricDifference2.removeAll(intersection);
// Present our results
System.out.println("Not in set A: " + notInSetA);
System.out.println("Not in set B: " + notInSetB);
System.out.println("Symmetric Difference: " + symmetricDifference);
System.out.println("Symmetric Difference 2: " + symmetricDifference2);
}
}
Output:
In set A: [Mary, Bob, Serena, John] In set B: [Mary, Bob, Jim, John] Not in set A: [Jim] Not in set B: [Serena] Symmetric Difference: [Jim, Serena] Symmetric Difference 2: [Jim, Serena]
JavaScript
ES5
Iterative
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
Clear JavaScript
function Difference(A,B)
{
var a = A.length, b = B.length, c = 0, C = [];
for (var i = 0; i < a; i++)
{ var j = 0, k = 0;
while (j < b && B[j] !== A[i]) j++;
while (k < c && C[k] !== A[i]) k++;
if (j == b && k == c) C[c++] = A[i];
}
return C;
}
function SymmetricDifference(A,B)
{
var D1 = Difference(A,B), D2 = Difference(B,A),
a = D1.length, b = D2.length;
for (var i = 0; i < b; i++) D1[a++] = D2[i];
return D1;
}
/* Example
A = ['John', 'Serena', 'Bob', 'Mary', 'Serena'];
B = ['Jim', 'Mary', 'John', 'Jim', 'Bob'];
Difference(A,B); // 'Serena'
Difference(B,A); // 'Jim'
SymmetricDifference(A,B); // 'Serena','Jim'
*/
ES6
Functional
By composition of generic functions;
(() => {
'use strict';
const symmetricDifference = (xs, ys) =>
union(difference(xs, ys), difference(ys, xs));
// GENERIC FUNCTIONS ------------------------------------------------------
// First instance of x (if any) removed from xs
// delete_ :: Eq a => a -> [a] -> [a]
const delete_ = (x, xs) => {
const i = xs.indexOf(x);
return i !== -1 ? (xs.slice(0, i)
.concat(xs.slice(i, -1))) : xs;
};
// (\\) :: (Eq a) => [a] -> [a] -> [a]
const difference = (xs, ys) =>
ys.reduce((a, x) => filter(z => z !== x, a), xs);
// filter :: (a -> Bool) -> [a] -> [a]
const filter = (f, xs) => xs.filter(f);
// flip :: (a -> b -> c) -> b -> a -> c
const flip = f => (a, b) => f.apply(null, [b, a]);
// foldl :: (b -> a -> b) -> b -> [a] -> b
const foldl = (f, a, xs) => xs.reduce(f, a);
// nub :: [a] -> [a]
const nub = xs => {
const mht = unconsMay(xs);
return mht.nothing ? xs : (
([h, t]) => [h].concat(nub(t.filter(s => s !== h)))
)(mht.just);
};
// show :: a -> String
const show = x => JSON.stringify(x, null, 2);
// unconsMay :: [a] -> Maybe (a, [a])
const unconsMay = xs => xs.length > 0 ? {
just: [xs[0], xs.slice(1)],
nothing: false
} : {
nothing: true
};
// union :: [a] -> [a] -> [a]
const union = (xs, ys) => {
const sx = nub(xs);
return sx.concat(foldl(flip(delete_), nub(ys), sx));
};
// TEST -------------------------------------------------------------------
const
a = ["John", "Serena", "Bob", "Mary", "Serena"],
b = ["Jim", "Mary", "John", "Jim", "Bob"];
return show(
symmetricDifference(a, b)
);
})();
- Output:
["Serena", "Jim"]
Procedural
const symmetricDifference = (...args) => {
let result = new Set();
for (const x of args)
for (const e of new Set(x))
if (result.has(e)) result.delete(e)
else result.add(e);
return [...result];
}
// TEST -------------------------------------------------------------------
console.log(symmetricDifference(["Jim", "Mary", "John", "Jim", "Bob"],["John", "Serena", "Bob", "Mary", "Serena"]));
console.log(symmetricDifference([1, 2, 5], [2, 3, 5], [3, 4, 5]));
- Output:
["Jim", "Serena"]
[1, 4, 5]
jq
The following implementation of symmetric_difference(a;b) makes no assumptions about the input lists except that neither contains null; given these assumptions, it is quite efficient. To workaround the no-null requirement would be tedious but straightforward.
# The following implementation of intersection (but not symmetric_difference) assumes that the
# elements of a (and of b) are unique and do not include null:
def intersection(a; b):
reduce ((a + b) | sort)[] as $i
([null, []]; if .[0] == $i then [null, .[1] + [$i]] else [$i, .[1]] end)
| .[1] ;
def symmetric_difference(a;b):
(a|unique) as $a | (b|unique) as $b
| (($a + $b) | unique) - (intersection($a;$b));
Example:
symmetric_difference( [1,2,1,2]; [2,3] )
[1,3]
Julia
Built-in function.
A = ["John", "Bob", "Mary", "Serena"]
B = ["Jim", "Mary", "John", "Bob"]
@show A B symdiff(A, B)
- Output:
A = String["John", "Bob", "Mary", "Serena"] B = String["Jim", "Mary", "John", "Bob"] symdiff(A, B) = String["Serena", "Jim"]
K
A: ?("John";"Bob";"Mary";"Serena")
B: ?("Jim";"Mary";"John";"Bob")
A _dvl B / in A but not in B
"Serena"
B _dvl A / in B but not in A
"Jim"
(A _dvl B;B _dvl A) / Symmetric difference
("Serena"
"Jim")
Kotlin
// version 1.1.2
fun main(args: Array<String>) {
val a = setOf("John", "Bob", "Mary", "Serena")
val b = setOf("Jim", "Mary", "John", "Bob")
println("A = $a")
println("B = $b")
val c = a - b
println("A \\ B = $c")
val d = b - a
println("B \\ A = $d")
val e = c.union(d)
println("A Δ B = $e")
}
- Output:
A = [John, Bob, Mary, Serena] B = [Jim, Mary, John, Bob] A \ B = [Serena] B \ A = [Jim] A Δ B = [Serena, Jim]
Ksh
#!/bin/ksh
# Symmetric difference - enumerate the items that are in A or B but not both.
# # Variables:
#
typeset -a A=( John Bob Mary Serena )
typeset -a B=( Jim Mary John Bob )
# # Functions:
#
# # Function _flattenarr(arr, sep) - flatten arr into string by separator sep
#
function _flattenarr {
typeset _arr ; nameref _arr="$1"
typeset _sep ; typeset -L1 _sep="$2"
typeset _buff
typeset _oldIFS=$IFS ; IFS="${_sep}"
_buff=${_arr[*]}
IFS="${_oldIFS}"
echo "${_buff}"
}
# # Function _notin(_arr1, _arr2) - elements in arr1 and not in arr2
#
function _notin {
typeset _ar1 ; nameref _ar1="$1"
typeset _ar2 ; nameref _ar2="$2"
typeset _i _buff _set ; integer _i
_buff=$(_flattenarr _ar2 \|)
for((_i=0; _i<${#_ar1[*]}; _i++)); do
[[ ${_ar1[_i]} != @(${_buff}) ]] && _set+="${_ar1[_i]} "
done
echo ${_set% *}
}
######
# main #
######
AnB=$(_notin A B) ; echo "A - B = ${AnB}"
BnA=$(_notin B A) ; echo "B - A = ${BnA}"
echo "A xor B = ${AnB} ${BnA}"
- Output:
A - B = SerenaB - A = Jim
A xor B = Serena Jim
Lasso
[
var(
'a' = array(
'John'
,'Bob'
,'Mary'
,'Serena'
)
,'b' = array
);
$b->insert( 'Jim' ); // Alternate method of populating array
$b->insert( 'Mary' );
$b->insert( 'John' );
$b->insert( 'Bob' );
$a->sort( true ); // arrays must be sorted (true = ascending) for difference to work
$b->sort( true );
$a->difference( $b )->union( $b->difference( $a ) );
]
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]
Lua
A = { ["John"] = true, ["Bob"] = true, ["Mary"] = true, ["Serena"] = true }
B = { ["Jim"] = true, ["Mary"] = true, ["John"] = true, ["Bob"] = true }
A_B = {}
for a in pairs(A) do
if not B[a] then A_B[a] = true end
end
B_A = {}
for b in pairs(B) do
if not A[b] then B_A[b] = true end
end
for a_b in pairs(A_B) do
print( a_b )
end
for b_a in pairs(B_A) do
print( b_a )
end
Object-oriented approach:
SetPrototype = {
__index = {
union = function(self, other)
local res = Set{}
for k in pairs(self) do res[k] = true end
for k in pairs(other) do res[k] = true end
return res
end,
intersection = function(self, other)
local res = Set{}
for k in pairs(self) do res[k] = other[k] end
return res
end,
difference = function(self, other)
local res = Set{}
for k in pairs(self) do
if not other[k] then res[k] = true end
end
return res
end,
symmetric_difference = function(self, other)
return self:difference(other):union(other:difference(self))
end
},
-- return string representation of set
__tostring = function(self)
-- list to collect all elements from the set
local l = {}
for k in pairs(self) do l[#l+1] = k end
return "{" .. table.concat(l, ", ") .. "}"
end,
-- allow concatenation with other types to yield string
__concat = function(a, b)
return (type(a) == 'string' and a or tostring(a)) ..
(type(b) == 'string' and b or tostring(b))
end
}
function Set(items)
local _set = {}
setmetatable(_set, SetPrototype)
for _, item in ipairs(items) do _set[item] = true end
return _set
end
A = Set{"John", "Serena", "Bob", "Mary", "Serena"}
B = Set{"Jim", "Mary", "John", "Jim", "Bob"}
print("Set A: " .. A)
print("Set B: " .. B)
print("\nSymm. difference (A\\B)∪(B\\A): " .. A:symmetric_difference(B))
print("Union A∪B : " .. A:union(B))
print("Intersection A∩B : " .. A:intersection(B))
print("Difference A\\B : " .. A:difference(B))
print("Difference B\\A : " .. B:difference(A))
Output:
Set A: {Serena, Mary, John, Bob} Set B: {Mary, Jim, John, Bob} Symm. difference (A\B)∪(B\A): {Serena, Jim} Union A∪B : {John, Serena, Jim, Mary, Bob} Intersection A∩B : {Mary, John, Bob} Difference A\B : {Serena} Difference B\A : {Jim}
Maple
Maple has built-in support for set operations. Assign the sets A and B:
A := {John, Bob, Mary, Serena};
B := {Jim, Mary, John, Bob};
Now compute the symmetric difference with the symmdiff command:
symmdiff(A, B);
- Output:
{Jim, Serena}
Mathematica/Wolfram Language
Mathematica has built-in support for operations on sets, using its generic symbolic lists. This function finds the entries in each list that are not present in the intersection of the two lists.
SymmetricDifference[x_List,y_List] := Join[Complement[x,Intersection[x,y]],Complement[y,Intersection[x,y]]]
For large lists, some performance improvement could be made by caching the intersection of the two lists to avoid computing it twice:
CachedSymmetricDifference[x_List,y_List] := Module[{intersect=Intersection[x,y]},Join[Complement[x,intersect],Complement[y,intersect]]]
Also, due to Mathematica's symbolic nature, these functions are automatically applicable to lists of any content, such as strings, integers, reals, graphics, or undefined generic symbols (e.g. unassigned variables).
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 complement 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
Maxima
/* builtin */
symmdifference({"John", "Bob", "Mary", "Serena"},
{"Jim", "Mary", "John", "Bob"});
{"Jim", "Serena"}
Mercury
:- module symdiff.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module list, set, string.
main(!IO) :-
A = set(["John", "Bob", "Mary", "Serena"]),
B = set(["Jim", "Mary", "John", "Bob"]),
print_set("A\\B", DiffAB @ (A `difference` B), !IO),
print_set("B\\A", DiffBA @ (B `difference` A), !IO),
print_set("A symdiff B", DiffAB `union` DiffBA, !IO).
:- pred print_set(string::in, set(T)::in, io::di, io::uo) is det.
print_set(Desc, Set, !IO) :-
to_sorted_list(Set, Elems),
io.format("%11s: %s\n", [s(Desc), s(string(Elems))], !IO).
MiniScript
Set = new map
Set["set"] = {}
Set.init = function(items)
set = new Set
set.set = {}
for item in items
set.add(item)
end for
return set
end function
Set.contains = function(item)
return self.set.hasIndex(item)
end function
Set.items = function
return self.set.indexes
end function
Set.add = function(item)
self.set[item] = true
end function
Set.union = function(other)
result = Set.init
result.set = self.set + other.set
return result
end function
Set.difference = function(other)
result = Set.init
for item in self.items
if not other.contains(item) then result.add(item)
end for
return result
end function
Set.symmetricDifference = function(other)
diff1 = self.difference(other)
diff2 = other.difference(self)
return diff1.union(diff2)
end function
a = ["John", "Serena", "Bob", "Mary", "Serena"]
b = ["Jim", "Mary", "John", "Jim", "Bob"]
A1 = Set.init(a)
B1 = Set.init(b)
print "A XOR B " + A1.symmetricDifference(B1).items
print "A - B " + A1.difference(B1).items
print "B - A " + B1.difference(A1).items
- Output:
A XOR B ["Serena", "Jim"] A - B ["Serena"] B - A ["Jim"]
Miranda
main :: [sys_message]
main = [Stdout (show (symdiff a b) ++ "\n")]
where a = ["John", "Serena", "Bob", "Mary", "Serena"]
b = ["Jim", "Mary", "John", "Jim", "Bob"]
symdiff :: [*]->[*]->[*]
symdiff a b = (a' -- b') ++ (b' -- a')
where a' = nub a
b' = nub b
nub :: [*]->[*]
nub = f []
where f acc [] = acc
f acc (a:as) = f acc as, if a $in acc
= f (a:acc) as, otherwise
in :: *->[*]->bool
in i [] = False
in i (a:as) = a == i \/ i $in as
- Output:
["Serena","Jim"]
Nim
import sets
var setA = ["John", "Bob", "Mary", "Serena"].toHashSet
var setB = ["Jim", "Mary", "John", "Bob"].toHashSet
echo setA -+- setB # Symmetric difference
echo setA - setB # Difference
echo setB - setA # Difference
Output:
{Serena, Jim} {Serena} {Jim}
Objective-C
#import <Foundation/Foundation.h>
int main(int argc, const char *argv[]) {
@autoreleasepool {
NSSet* setA = [NSSet setWithObjects:@"John", @"Serena", @"Bob", @"Mary", @"Serena", nil];
NSSet* setB = [NSSet setWithObjects:@"Jim", @"Mary", @"John", @"Jim", @"Bob", nil];
// Present our initial data set
NSLog(@"In set A: %@", setA);
NSLog(@"In set B: %@", setB);
// Get our individual differences.
NSMutableSet* notInSetA = [NSMutableSet setWithSet:setB];
[notInSetA minusSet:setA];
NSMutableSet* notInSetB = [NSMutableSet setWithSet:setA];
[notInSetB minusSet:setB];
// The symmetric difference is the concatenation of the two individual differences
NSMutableSet* symmetricDifference = [NSMutableSet setWithSet:notInSetA];
[symmetricDifference unionSet:notInSetB];
// Present our results
NSLog(@"Not in set A: %@", notInSetA);
NSLog(@"Not in set B: %@", notInSetB);
NSLog(@"Symmetric Difference: %@", symmetricDifference);
}
return 0;
}
OCaml
let unique lst =
let f lst x = if List.mem x lst then lst else x::lst in
List.rev (List.fold_left f [] lst)
let ( -| ) a b =
unique (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"]
ooRexx
a = .set~of("John", "Bob", "Mary", "Serena")
b = .set~of("Jim", "Mary", "John", "Bob")
-- the xor operation is a symmetric difference
do item over a~xor(b)
say item
end
Output:
Serena Jim
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}}
PARI/GP
sd(u,v)={
my(r=List());
u=vecsort(u,,8);
v=vecsort(v,,8);
for(i=1,#u,if(!setsearch(v,u[i]),listput(r,u[i])));
for(i=1,#v,if(!setsearch(u,v[i]),listput(r,v[i])));
Vec(r)
};
sd(["John", "Serena", "Bob", "Mary", "Serena"],["Jim", "Mary", "John", "Jim", "Bob"])
Pascal
PROGRAM Symmetric_difference;
TYPE
TName = (Bob, Jim, John, Mary, Serena);
TList = SET OF TName;
PROCEDURE Put(txt : String; ResSet : TList);
VAR
I : TName;
BEGIN
Write(txt);
FOR I IN ResSet DO Write(I,' ');
WriteLn
END;
VAR
ListA : TList = [John, Bob, Mary, Serena];
ListB : TList = [Jim, Mary, John, Bob];
BEGIN
Put('ListA -> ', ListA);
Put('ListB -> ', ListB);
Put('ListA >< ListB -> ', (ListA - ListB) + (ListB - ListA));
Put('ListA - ListB -> ', ListA - ListB);
Put('ListB - ListA -> ', ListB - ListA);
ReadLn;
END.
- Output:
ListA -> Bob John Mary Serena ListB -> Bob Jim John Mary ListA >< ListB -> Jim Serena ListA - ListB -> Serena ListB - ListA -> Jim
Object Pascal actually has a 'Symmetric Difference' operator `> <`:
program SymmetricDifference;
type
charSet = set of Char;
var
s1, s2, s3: charSet;
ch: char;
begin
s1 := ['a', 'b', 'c', 'd'];
s2 := ['c', 'd', 'e', 'f'];
s3 := s1 >< s2;
for ch in s3 do
write(ch, ' ');
writeLn;
end.
Output:
a b e f
Perl
sub symm_diff {
# two lists passed in as references
my %in_a = map(($_=>1), @{+shift});
my %in_b = map(($_=>1), @{+shift});
my @a = grep { !$in_b{$_} } keys %in_a;
my @b = grep { !$in_a{$_} } keys %in_b;
# return A-B, B-A, A xor B as ref to lists
return \@a, \@b, [ @a, @b ]
}
my @a = qw(John Serena Bob Mary Serena);
my @b = qw(Jim Mary John Jim Bob );
my ($a, $b, $s) = symm_diff(\@a, \@b);
print "A\\B: @$a\nB\\A: @$b\nSymm: @$s\n";
- Output:
A\B: Serena B\A: Jim Symm: Serena Jim
Phix
function Union(sequence a, sequence b) for i=1 to length(a) do if not find(a[i],b) then b = append(b,a[i]) end if end for return b end function function Difference(sequence a, sequence b) sequence res = {} for i=1 to length(a) do if not find(a[i],b) and not find(a[i],res) then res = append(res,a[i]) end if end for return res end function function Symmetric_Difference(sequence a, sequence b) return Union(Difference(a, b), Difference(b, a)) end function sequence a = {"John", "Serena", "Bob", "Mary", "Serena"}, b = {"Jim", "Mary", "John", "Jim", "Bob"} ?Symmetric_Difference(a,a) ?Symmetric_Difference(a,b) ?Symmetric_Difference(b,a) ?Symmetric_Difference(b,b)
- Output:
{} {"Jim","Serena"} {"Serena","Jim"} {}
You can also use the builtin (which defaults to symmetic differences), though it will crash if you pass it "sets" with duplicate elements.
include sets.e sequence a = {"John", "Serena", "Bob", "Mary"}, b = {"Jim", "Mary", "John", "Bob"} ?difference(a,a) ?difference(a,b) ?difference(b,a) ?difference(b,b)
Same output as above
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
Picat
Using the ordset
module.
import ordset.
go =>
A = ["John", "Serena", "Bob", "Mary", "Serena"].new_ordset(),
B = ["Jim", "Mary", "John", "Jim", "Bob"].new_ordset(),
println(symmetric_difference=symmetric_difference(A,B)),
println(symmetric_difference2=symmetric_difference2(A,B)),
println(subtractAB=subtract(A,B)),
println(subtractBA=subtract(B,A)),
println(union=union(A,B)),
println(intersection=intersection(A,B)),
nl.
symmetric_difference(A,B) = union(subtract(A,B), subtract(B,A)).
% variant
symmetric_difference2(A,B) = subtract(union(A,B), intersection(B,A)).
- Output:
symmetric_difference = [Jim,Serena] symmetric_difference2 = [Jim,Serena] subtractAB = [Serena] subtractBA = [Jim] union = [Bob,Jim,John,Mary,Serena] intersection = [Bob,John,Mary]
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)
Pike
The set type in Pike is 'multiset', that is, a value may appear multiple times and the difference operator only removes equal amounts of duplicates.
> multiset(string) A = (< "John", "Serena", "Bob", "Mary", "Bob", "Serena" >);
> multiset(string) B = (< "Jim", "Mary", "Mary", "John", "Bob", "Jim" >);
> A^B;
Result: (< "Bob", "Serena", "Serena", "Mary", "Jim", "Jim" >)
The ^
operator treats arrays like multisets.
> array(string) A = ({ "John", "Serena", "Bob", "Mary", "Serena", "Bob" });
> array(string) B = ({ "Jim", "Mary", "John", "Jim", "Bob", "Mary" });
> A^B;
Result: ({ "Serena", "Serena", "Bob", "Jim", "Jim", "Mary"})
> Array.uniq((A-B)+(B-A));
Result: ({ "Serena", "Jim" })
Set operations are also possible with mappings. Here the difference operator works as expected:
> mapping(string:int) A = ([ "John":1, "Serena":1, "Bob":1, "Mary":1 ]);
> mapping(string:int) B = ([ "Jim":1, "Mary":1, "John":1, "Bob":1 ]);
> A^B;
Result: ([ "Jim": 1, "Serena": 1 ])
Lastly, there is a Set class.
> ADT.Set A = ADT.Set((< "John", "Serena", "Bob", "Mary", "Serena", "Bob" >));
> ADT.Set B = ADT.Set((< "Jim", "Mary", "John", "Jim", "Bob", "Mary" >));
> (A-B)+(B-A);
Result: ADT.Set({ "Serena", "Jim" })
PL/I
/* PL/I ***************************************************************
* 17.08.2013 Walter Pachl
**********************************************************************/
*process source attributes xref;
sd: Proc Options(main);
Dcl a(4) Char(20) Var Init('John','Bob','Mary','Serena');
Dcl b(4) Char(20) Var Init('Jim','Mary','John','Bob');
Call match(a,b);
Call match(b,a);
match: Proc(x,y);
Dcl (x(*),y(*)) Char(*) Var;
Dcl (i,j) Bin Fixed(31);
Do i=1 To hbound(x);
Do j=1 To hbound(y);
If x(i)=y(j) Then Leave;
End;
If j>hbound(y) Then
Put Edit(x(i))(Skip,a);
End;
End;
End;
Output:
Serena Jim
PowerShell
$A = @( "John"
"Bob"
"Mary"
"Serena" )
$B = @( "Jim"
"Mary"
"John"
"Bob" )
# Full commandlet name and full parameter names
Compare-Object -ReferenceObject $A -DifferenceObject $B
# Same commandlet using an alias and positional parameters
Compare $A $B
# A - B
Compare $A $B | Where SideIndicator -eq "<=" | Select -ExpandProperty InputObject
# B - A
Compare $A $B | Where SideIndicator -eq "=>" | Select -ExpandProperty InputObject
- Output:
InputObject SideIndicator ----------- ------------- Jim => Serena <= InputObject SideIndicator ----------- ------------- Jim => Serena <= Serena Jim
Prolog
sym_diff :-
A = ['John', 'Serena', 'Bob', 'Mary', 'Serena'],
B = ['Jim', 'Mary', 'John', 'Jim', 'Bob'],
format('A : ~w~n', [A]),
format('B : ~w~n', [B]),
list_to_set(A, SA),
list_to_set(B, SB),
format('set from A : ~w~n', [SA]),
format('set from B : ~w~n', [SB]),
subtract(SA, SB, DAB),
format('difference A\\B : ~w~n', [DAB]),
subtract(SB, SA, DBA),
format('difference B\\A : ~w~n', [DBA]),
union(DAB, DBA, Diff),
format('symetric difference : ~w~n', [Diff]).
output :
A : [John,Serena,Bob,Mary,Serena] B : [Jim,Mary,John,Jim,Bob] set from A : [John,Serena,Bob,Mary] set from B : [Jim,Mary,John,Bob] difference A\B : [Serena] difference B\A : [Jim] symetric difference : [Serena,Jim] true.
PureBasic
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
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
Python
Python's set
type supports difference as well as symmetric difference operators.
Python 3.x and Python 2.7 have syntax for set literals:
>>> setA = {"John", "Bob", "Mary", "Serena"}
>>> setB = {"Jim", "Mary", "John", "Bob"}
>>> setA ^ setB # symmetric difference of A and B
{'Jim', 'Serena'}
>>> setA - setB # elements in A that are not in B
{'Serena'}
>>> setB - setA # elements in B that are not in A
{'Jim'}
>>> setA | setB # elements in A or B (union)
{'John', 'Bob', 'Jim', 'Serena', 'Mary'}
>>> setA & setB # elements in both A and B (intersection)
{'Bob', 'John', 'Mary'}
Note that the order of set elements is undefined.
Earlier versions of Python:
>>> 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'])
>>> # and so on...
There is also a method call interface for these operations. In contrast to the operators above, they accept any iterables as arguments not just sets.
>>> setA.symmetric_difference(setB)
{'Jim', 'Serena'}
>>> setA.difference(setB)
{'Serena'}
>>> setB.difference(setA)
{'Jim'}
>>> setA.union(setB)
{'Jim', 'Mary', 'Serena', 'John', 'Bob'}
>>> setA.intersection(setB)
{'Mary', 'John', 'Bob'}
Quackery
[ $ "rosetta/bitwisesets.qky" loadfile ] now!
( i.e. using the Quackery code for sets at
http://rosettacode.org/wiki/Set#Indexed_Bitmaps )
set{ John Bob Mary Serena }set is A ( --> { )
set{ Jim Mary John Bob }set is B ( --> { )
say "A \ B is " A B difference echoset cr
say "B \ A is " B A difference echoset cr
say "(A \ B) U (B \ A) is "
A B difference B A difference union echoset cr
say "(A U B) \ (A n B) is "
A B union A B intersection difference echoset cr
say "Using built-in symmetric difference: "
A B symmdiff echoset cr
- Output:
A \ B is { Serena } B \ A is { Jim } (A \ B) U (B \ A) is { Jim Serena } (A U B) \ (A n B) is { Jim Serena } Using built-in symmetric difference: { Jim Serena }
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"
Racket
#lang racket
(define A (set "John" "Bob" "Mary" "Serena"))
(define B (set "Jim" "Mary" "John" "Bob"))
(set-symmetric-difference A B)
(set-subtract A B)
(set-subtract B A)
Raku
(formerly Perl 6)
my \A = set <John Serena Bob Mary Serena>;
my \B = set <Jim Mary John Jim Bob>;
say A ∖ B; # Set subtraction
say B ∖ A; # Set subtraction
say (A ∪ B) ∖ (A ∩ B); # Symmetric difference, via basic set operations
say A ⊖ B; # Symmetric difference, via dedicated operator
- Output:
set(Serena) set(Jim) set(Jim, Serena) set(Jim, Serena)
REBOL
a: [John Serena Bob Mary Serena]
b: [Jim Mary John Jim Bob]
difference a b
Result is
[Serena Jim]
Refal
$ENTRY Go {
, John Bob Mary Serena: e.A
, Jim Mary John Bob: e.B
= <Prout <Symdiff (e.A) (e.B)>>;
};
Symdiff {
(e.1) (e.2), <Diff (<Set e.1>) (<Set e.2>)>: e.3
, <Diff (<Set e.2>) (<Set e.1>)>: e.4
= <Union (e.3) (e.4)>;
};
Set {
= ;
s.1 e.1 s.1 e.2 = <Set e.1 s.1 e.2>;
s.1 e.1 = s.1 <Set e.1>;
};
Union {
(e.1) (e.2) = <Set e.1 e.2>;
};
Diff {
() (e.1) = ;
(e.1) () = e.1;
(s.1 e.1) (e.2 s.1 e.3) = <Diff (e.1) (e.2 e.3)>;
(s.1 e.1) (e.2) = s.1 <Diff (e.1) (e.2)>;
};
- Output:
Serena Jim
REXX
version 1
This REXX version shows the symmetric difference and symmetric AND between two lists, the lists have duplicate elements to show their proper handling.
The lists (and output) are formatted as a set.
The set elements may contain any character permitted with a REXX literal, including the literal character itself (expressed as a double literal delimiter), blanks, brackets, commas, and also a null value.
/*REXX program finds symmetric difference and symmetric AND (between two lists). */
a= '["John", "Serena", "Bob", "Mary", "Serena"]' /*note the duplicate element: Serena */
b= '["Jim", "Mary", "John", "Jim", "Bob"]' /* " " " " Jim */
a.=0; SD.=0; SA.=0; SD=; SA= /*falsify booleans; zero & nullify vars*/
a.1=a; say '──────────────list A =' a /*assign a list and display it to term.*/
a.2=b; say '──────────────list B =' b /* " " " " " " " " */
/* [↓] parse the two lists. */
do k=1 for 2 /*process both lists (stemmed array). */
a.k=strip( strip(a.k, , "["), ,']') /*strip leading and trailing brackets. */
do j=1 until a.k='' /*parse names [they may have blanks]. */
a.k=strip(a.k, , ',') /*strip all commas (if there are any). */
parse var a.k '"' _ '"' a.k /*obtain the name of the list. */
a.k.j=_ /*store the name of the list. */
a.k._=1 /*make a boolean value. */
end /*j*/
a.k.0=j-1 /*the number of this list (of names). */
end /*k*/
say /* [↓] find the symmetric difference. */
do k=1 for 2; ko=word(2 1, k) /*process both lists; KO=other list. */
do j=1 for a.k.0; _=a.k.j /*process the list names. */
if \a.ko._ & \SD._ then do; SD._=1 /*if not in both, then ··· */
SD=SD '"'_'",' /*add to symmetric difference list. */
end
end /*j*/
end /*k*/
/* [↓] SD ≡ symmetric difference. */
SD= "["strip( strip(SD), 'T', ",")']' /*clean up and add brackets [ ] to it.*/
say 'symmetric difference =' SD /*display the symmetric difference. */
/* [↓] locate the symmetric AND. */
do j=1 for a.1.0; _=a.1.j /*process the A list names. */
if a.1._ & a.2._ & \SA._ then do; SA._=1 /*if it's common to both, then ··· */
SA=SA '"'_'",' /*add to symmetric AND list. */
end
end /*j*/
say /* [↓] SA ≡ symmetric AND. */
SA= "["strip( strip(SA), 'T', ",")']' /*clean up and add brackets [ ] to it.*/
say ' symmetric AND =' SA /*stick a fork in it, we're all done. */
- output when using the in-program lists:
──────────────list A = ["John", "Serena", "Bob", "Mary", "Serena"] ──────────────list B = ["Jim", "Mary", "John", "Jim", "Bob"] symmetric difference = ["Serena", "Jim"] symmetric AND = ["John", "Bob", "Mary"]
version 1.5
This REXX version shows the symmetric difference and symmetric AND between two lists, the lists have items that have imbedded blanks in them as well as some punctuation, and also a null element.
/*REXX pgm finds symmetric difference and symm. AND (between two lists).*/
a.=0 /*falsify the booleans*/
a= '["Zahn", "Yi", "Stands with a Fist", "", "Hungry Wolf", "Yi"]'
b= '["Draag Ng [Jr.]", "Patzy", "Zahn", "Yi", "Robert the Bruce"]'
∙
∙
∙
- output when using the in-program lists (which has imbedded blanks):
──────────────list A = ["Zahn", "Yi", "Stands with a Fist", "", "Hungry Wolf", "Yi"] ──────────────list B = ["Draag Ng [Jr.]", "Patzy", "Zahn", "Yi", "Robert the Bruce"] symmetric difference = ["Stands with a Fist", "", "Hungry Wolf", "Draag Ng [Jr.]", "Patzy"] symmetric AND = ["Zahn", "Yi"]
version 2
/* REXX ---------------------------------------------------------------
* 14.12.2013 Walter Pachl a short solution
* 16.12.2013 fix duplicate element problem in input
* 16.12.2013 added duplicate to t.
* Handles only sets the elements of which do not contain blanks
*--------------------------------------------------------------------*/
s='John Bob Mary Serena'
t='Jim Mary John Bob Jim '
Say difference(s,t)
Exit
difference:
Parse Arg a,b
res=''
Do i=1 To words(a)
If wordpos(word(a,i),b)=0 Then
Call out word(a,i)
End
Do i=1 To words(b)
If wordpos(word(b,i),a)=0 Then
Call out word(b,i)
End
Return strip(res)
out: parse Arg e
If wordpos(e,res)=0 Then res=res e
Return
Output:
Serena Jim
Ring
alist = []
blist = []
alist = ["john", "bob", "mary", "serena"]
blist = ["jim", "mary", "john", "bob"]
alist2 = []
for i = 1 to len(alist)
flag = 0
for j = 1 to len(blist)
if alist[i] = blist[j] flag = 1 ok
next
if (flag = 0) add(alist2, alist[i]) ok
next
blist2 = []
for j = 1 to len(alist)
flag = 0
for i = 1 to len(blist)
if alist[i] = blist[j] flag = 1 ok
next
if (flag = 0) add(blist2, blist[j]) ok
next
see "a xor b :" see nl
see alist2
see blist2 see nl
see "a-b :" see nl
see alist2 see nl
see "b-a :" see nl
see blist2 see nl
RPL
DIFFL
is defined at Set
≪ DUP2 DIFFL ROT ROT SWAP DIFFL + ≫ ≫ 'SYMDIFF' STO
{"John" "Bob" "Mary" "Serena"} {"Jim" "Mary" "John" "Bob"} SYMDIFF
- Output:
1: {"Jim" "Serena"}
Ruby
With arrays:
a = ["John", "Serena", "Bob", "Mary", "Serena"]
b = ["Jim", "Mary", "John", "Jim", "Bob"]
# the union minus the intersection:
p sym_diff = (a | b)-(a & b) # => ["Serena", "Jim"]
Class Set has a symmetric difference operator built-in:
require 'set'
a = Set["John", "Serena", "Bob", "Mary", "Serena"] #Set removes duplicates
b = Set["Jim", "Mary", "John", "Jim", "Bob"]
p sym_diff = a ^ b # => #<Set: {"Jim", "Serena"}>
Run BASIC
setA$ = "John,Bob,Mary,Serena"
setB$ = "Jim,Mary,John,Bob"
x$ = b$(setA$,setB$)
print word$(x$,1,",")
c$ = c$ + x$
x$ = b$(setB$,setA$)
print word$(x$,1,",")
print c$;x$
end
function b$(a$,b$)
i = 1
while word$(a$,i,",") <> ""
a1$ = word$(a$,i,",")
j = instr(b$,a1$)
if j <> 0 then b$ = left$(b$,j-1) + mid$(b$,j+len(a1$)+1)
i = i + 1
wend
end function
Jim Serena Jim,Serena
Rust
Both set types in the std-lib -- HashSet and BTreeSet -- implement a symmetric_difference method.
use std::collections::HashSet;
fn main() {
let a: HashSet<_> = ["John", "Bob", "Mary", "Serena"]
.iter()
.collect();
let b = ["Jim", "Mary", "John", "Bob"]
.iter()
.collect();
let diff = a.symmetric_difference(&b);
println!("{:?}", diff);
}
- Output:
["Serena", "Jim"]
Scala
scala> val s1 = Set("John", "Serena", "Bob", "Mary", "Serena")
s1: scala.collection.immutable.Set[java.lang.String] = Set(John, Serena, Bob, Mary)
scala> val s2 = Set("Jim", "Mary", "John", "Jim", "Bob")
s2: scala.collection.immutable.Set[java.lang.String] = Set(Jim, Mary, John, Bob)
scala> (s1 diff s2) union (s2 diff s1)
res46: scala.collection.immutable.Set[java.lang.String] = Set(Serena, Jim)
Scheme
Pure R7RS
In pure Scheme, to illustrate implementation of the algorithms:
(import (scheme base)
(scheme write))
;; -- given two sets represented as lists, return (A \ B)
(define (a-without-b a b)
(cond ((null? a)
'())
((member (car a) (cdr a)) ; drop head of a if it's a duplicate
(a-without-b (cdr a) b))
((member (car a) b) ; head of a is in b so drop it
(a-without-b (cdr a) b))
(else ; head of a not in b, so keep it
(cons (car a) (a-without-b (cdr a) b)))))
;; -- given two sets represented as lists, return symmetric difference
(define (symmetric-difference a b)
(append (a-without-b a b)
(a-without-b b a)))
;; -- test case
(define A '(John Bob Mary Serena))
(define B '(Jim Mary John Bob))
(display "A\\B: ") (display (a-without-b A B)) (newline)
(display "B\\A: ") (display (a-without-b B A)) (newline)
(display "Symmetric difference: ") (display (symmetric-difference A B)) (newline)
;; -- extra test as we are using lists
(display "Symmetric difference 2: ")
(display (symmetric-difference '(John Serena Bob Mary Serena)
'(Jim Mary John Jim Bob))) (newline)
- Output:
A\B: (Serena) B\A: (Jim) Symmetric difference: (Serena Jim) Symmetric difference 2: (Serena Jim)
Using a standard library
SRFI 1 is one of the most popular SRFIs. It deals with lists, but also has functions treating lists as sets. The lset functions assume the inputs are sets, so we must delete duplicates if this property is not guaranteed on input.
(import (scheme base)
(scheme write)
(srfi 1))
(define (a-without-b a b)
(lset-difference equal?
(delete-duplicates a)
(delete-duplicates b)))
(define (symmetric-difference a b)
(lset-xor equal?
(delete-duplicates a)
(delete-duplicates b)))
;; -- test case
(define A '(John Bob Mary Serena))
(define B '(Jim Mary John Bob))
(display "A\\B: ") (display (a-without-b A B)) (newline)
(display "B\\A: ") (display (a-without-b B A)) (newline)
(display "Symmetric difference: ") (display (symmetric-difference A B)) (newline)
;; -- extra test as we are using lists
(display "Symmetric difference 2: ")
(display (symmetric-difference '(John Serena Bob Mary Serena)
'(Jim Mary John Jim Bob))) (newline)
Seed7
$ include "seed7_05.s7i";
const type: striSet is set of string;
enable_output(striSet);
const proc: main is func
local
const striSet: setA is {"John", "Bob" , "Mary", "Serena"};
const striSet: setB is {"Jim" , "Mary", "John", "Bob" };
begin
writeln(setA >< setB);
end func;
Output:
{Jim, Serena}
SETL
program symmetric_difference;
A := {"John", "Bob", "Mary", "Serena"};
B := {"Jim", "Mary", "John", "Bob"};
print("A - B:", A - B);
print("B - A:", B - A);
print("Symmetric difference:", (A-B) + (B-A));
end program;
- Output:
A - B: {Serena} B - A: {Jim} Symmetric difference: {Jim Serena}
Sidef
var a = ["John", "Serena", "Bob", "Mary", "Serena"];
var b = ["Jim", "Mary", "John", "Jim", "Bob"];
a ^ b -> unique.dump.say;
- Output:
["Serena", "Jim"]
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' )
SQL/PostgreSQL
create or replace function arrxor(anyarray,anyarray) returns anyarray as $$
select ARRAY(
(
select r.elements
from (
(select 1,unnest($1))
union all
(select 2,unnest($2))
) as r (arr, elements)
group by 1
having min(arr) = max(arr)
)
)
$$ language sql strict immutable;
Usage:
select arrxor('{this,is,a,test}'::text[],'{also,part,of,a,test}'::text[]);
Output:
arrxor ------------------------ also,is,of,part,this
Swift
Swift's Set
type supports difference as well as symmetric difference operators.
let setA : Set<String> = ["John", "Bob", "Mary", "Serena"]
let setB : Set<String> = ["Jim", "Mary", "John", "Bob"]
println(setA.exclusiveOr(setB)) // symmetric difference of A and B
println(setA.subtract(setB)) // elements in A that are not in B
- Output:
["Jim", "Serena"] ["Serena"]
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.
package require struct::set
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]"
Produces this output:
A\B = Serena B\A = Jim A⊖B = Jim Serena Direct Check: Jim Serena
TUSCRIPT
$$ MODE TUSCRIPT
a="John'Bob'Mary'Serena"
b="Jim'Mary'John'Bob"
DICT names CREATE
SUBMACRO checknames
!var,val
PRINT val,": ",var
LOOP n=var
DICT names APPEND/QUIET n,num,cnt,val;" "
ENDLOOP
ENDSUBMACRO
CALL checknames (a,"a")
CALL checknames (b,"b")
DICT names UNLOAD names,num,cnt,val
LOOP n=names,v=val
PRINT n," in: ",v
ENDLOOP
Output:
a: John'Bob'Mary'Serena b: Jim'Mary'John'Bob John in: a b Bob in: a b Mary in: a b Serena in: a Jim in: b
UNIX Shell
uniq() {
u=("$@")
for ((i=0;i<${#u[@]};i++)); do
for ((j=i+1;j<=${#u[@]};j++)); do
[ "${u[$i]}" = "${u[$j]}" ] && unset u[$i]
done
done
u=("${u[@]}")
}
a=(John Serena Bob Mary Serena)
b=(Jim Mary John Jim Bob)
uniq "${a[@]}"
au=("${u[@]}")
uniq "${b[@]}"
bu=("${u[@]}")
ab=("${au[@]}")
for ((i=0;i<=${#au[@]};i++)); do
for ((j=0;j<=${#bu[@]};j++)); do
[ "${ab[$i]}" = "${bu[$j]}" ] && unset ab[$i]
done
done
ab=("${ab[@]}")
ba=("${bu[@]}")
for ((i=0;i<=${#bu[@]};i++)); do
for ((j=0;j<=${#au[@]};j++)); do
[ "${ba[$i]}" = "${au[$j]}" ] && unset ba[$i]
done
done
ba=("${ba[@]}")
sd=("${ab[@]}" "${ba[@]}")
echo "Set A = ${a[@]}"
echo " = ${au[@]}"
echo "Set B = ${b[@]}"
echo " = ${bu[@]}"
echo "A - B = ${ab[@]}"
echo "B - A = ${ba[@]}"
echo "Symmetric difference = ${sd[@]}"
Output:
Set A = John Serena Bob Mary Serena = John Bob Mary Serena Set B = Jim Mary John Jim Bob = Mary John Jim Bob A - B = Serena B - A = Jim Symmetric difference = Serena Jim
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'>>
V (Vlang)
const
(
alist = ["john", "bob", "mary", "serena"]
blist = ["jim", "mary", "john", "bob"]
)
fn main() {
mut rlist := []string{}
for elem in alist {
if blist.any(it == elem) == false {
println("a - b = $elem")
rlist << elem
}
}
for elem in blist {
if alist.any(it == elem) == false {
println("b - a = $elem")
rlist << elem
}
}
println("symmetric difference: $rlist")
}
- Output:
a - b = serena b - a = jim symmetric difference: ['serena', 'jim']
Wren
import "./set" for Set
var symmetricDifference = Fn.new { |a, b| a.except(b).union(b.except(a)) }
var a = Set.new(["John", "Bob", "Mary", "Serena"])
var b = Set.new(["Jim", "Mary", "John", "Bob"])
System.print("A = %(a)")
System.print("B = %(b)")
System.print("A - B = %(a.except(b))")
System.print("B - A = %(b.except(a))")
System.print("A △ B = %(symmetricDifference.call(a, b))")
- Output:
A = <Serena, Bob, Mary, John> B = <Jim, Bob, Mary, John> A - B = <Serena> B - A = <Jim> A △ B = <Serena, Jim>
XPL0
An integer in XPL0 can represent a set of up to 32 elements, and bitwise Boolean operations can represent union, intersection, and difference.
def John, Bob, Mary, Serena, Jim; \enumerate set items (0..4)
proc SetOut(S); \Output the elements in set
int S;
int Name, I;
[Name:= ["John", "Bob", "Mary", "Serena", "Jim"];
for I:= 0 to 31 do
if S & 1<<I then
[Text(0, Name(I)); ChOut(0, ^ )];
CrLf(0);
];
int A, B;
[A:= 1<<John ! 1<<Bob ! 1<<Mary ! 1<<Serena;
B:= 1<<Jim ! 1<<Mary ! 1<<John ! 1<<Bob;
Text(0, "A xor B = "); SetOut(A | B);
Text(0, "A\B = "); SetOut(A & ~B);
Text(0, "B\A = "); SetOut(B & ~A);
Text(0, "A\B U B\A = "); SetOut(A&~B ! B&~A);
]
- Output:
A xor B = Serena Jim A\B = Serena B\A = Jim A\B U B\A = Serena Jim
Yabasic
lista1$ = "John Serena Bob Mary Serena"
lista2$ = "Jim Mary John Jim Bob"
lista1$ = quitadup$(lista1$)
lista2$ = quitadup$(lista2$)
res$ = quitacomun$(lista1$, lista2$)
res$ = res$ + quitacomun$(lista2$, lista1$)
print res$
sub quitadup$(l$)
l$ = l$ + " "
return quitarep$(l$)
end sub
sub quitacomun$(l1$, l2$)
l1$ = l1$ + " "
l2$ = l2$ + " "
return quitarep$(l1$, l2$)
end sub
sub quitarep$(l1$, l2$)
local pos, n, x, listar$, nombre$, largo
largo = len(l1$)
pos = 1
while(true)
n = instr(l1$, " ", pos)
if n > 0 then
nombre$ = mid$(l1$, pos, n-pos)
if numparams = 1 then
x = instr(listar$, nombre$)
else
x = instr(l2$, nombre$)
end if
if x = 0 listar$ = listar$ + nombre$ + " "
pos = n + 1
else
return listar$
end if
wend
end sub
zkl
fcn setCommon(list1,list2){ list1.filter(list2.holds); }
fcn sdiff(list1,list2)
{ list1.extend(list2).copy().removeEach(setCommon(list1,list2)) }
a:=T("John","Bob","Mary","Serena");
b:=T("Jim","Mary","John","Bob");
sdiff(a,b).println();
To deal with duplicates, use Remove duplicate elements#zkl:
a:=T("John", "Serena", "Bob", "Mary", "Serena");
b:=T("Jim", "Mary", "John", "Jim", "Bob");
sdiff(a,b) : Utils.Helpers.listUnique(_).println();
- Output:
L("Serena","Jim") L("Serena","Jim")
- Programming Tasks
- Discrete math
- 11l
- Action!
- Action! Tool Kit
- Ada
- Aime
- ALGOL 68
- Amazing Hopper
- Apex
- APL
- AppleScript
- Arturo
- AutoHotkey
- AWK
- BBC BASIC
- Bracmat
- C
- C sharp
- C++
- Clojure
- Common Lisp
- D
- Datalog
- Delphi
- System.Typinfo
- Déjà Vu
- E
- EasyLang
- Eiffel
- Elixir
- Erlang
- F Sharp
- Factor
- Forth
- Fortran
- FreeBASIC
- Frink
- FutureBasic
- GAP
- Go
- Groovy
- Haskell
- HicEst
- Icon
- Unicon
- J
- Java
- JavaScript
- Jq
- Julia
- K
- Kotlin
- Ksh
- Lasso
- Logo
- Lua
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Maxima
- Mercury
- MiniScript
- Miranda
- Nim
- Objective-C
- OCaml
- OoRexx
- Oz
- PARI/GP
- Pascal
- Perl
- Phix
- PHP
- Picat
- PicoLisp
- Pike
- PL/I
- PowerShell
- Prolog
- PureBasic
- Python
- Quackery
- R
- Racket
- Raku
- REBOL
- Refal
- REXX
- Ring
- RPL
- Ruby
- Run BASIC
- Rust
- Scala
- Scheme
- Scheme/SRFIs
- Seed7
- SETL
- Sidef
- Smalltalk
- SQL
- PostgreSQL
- Swift
- Tcl
- Tcllib
- TUSCRIPT
- UNIX Shell
- Ursala
- V (Vlang)
- Wren
- Wren-set
- XPL0
- Yabasic
- Zkl
- Pages with too many expensive parser function calls