I am trying to figure out a solution for symmetric difference using javascript that accomplishes the following objectives:
- accepts an unspecified number of arrays as arguments
- preserves the original order of the numbers in the arrays
- does not remove duplicates of numbers in single arrays
- removes duplicates occurring across arrays
Thus, for example, if the input is ([1, 1, 2, 6], [2, 3, 5], [2, 3, 4]), the solution would be, [1, 1, 6, 5, 4].
I am trying to solve this as challenge given by an online coding community. The exact instructions of the challenge state,
Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.
The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.
Although my solution below finds the numbers that are unique to each array, it eliminates all numbers occuring more than once and does not keep the order of the numbers.
My question is very close to the one asked at finding symmetric difference/unique elements in multiple arrays in javascript. However, the solution does not preserve the original order of the numbers and does not preserve duplicates of unique numbers occurring in single arrays.
function sym(args){
var arr = [];
var result = [];
var units;
var index = {};
for(var i in arguments){
units = arguments[i];
for(var j = 0; j < units.length; j++){
arr.push(units[j]);
}
}
arr.forEach(function(a){
if(!index[a]){
index[a] = 0;
}
index[a]++;
});
for(var l in index){
if(index[l] === 1){
result.push(+l);
}
}
return result;
}
symsym([1, 1, 2, 6], [2, 3, 5], [2, 3, 4]); // => Desired answer: [1, 1, 6. 5. 4]
Here's a version that uses the
Set
object to make for faster lookup. Here's the basic logic:So, it starts with the first array
[1, 1, 2, 6]
. Since1
is not found in either of the other arrays, each of the first two1
values are added to the result. Then2
is found in the second set so it is not added to the result. Then6
is not found in either of the other two sets so it is added to the result. The same process repeats for the second array[2, 3, 5]
where2
and3
are found in other Sets, but5
is not so5
is added to the result. And, for the last array, only4
is not found in the other Sets. So, the final result is[1,1,6,5,4]
.The
Set
objects are used for convenience and performance. One could use.indexOf()
to look them up in each array or one could make your own Set-like lookup with a plain object if you didn't want to rely on the Set object. There's also a partial polyfill for the Set object that would work here in this answer.One key part of this code is how it compares a given item to the Sets from the other arrays. It just iterates through the list of Set objects, but it skips the Set object that has the same index in the array as the array being iterated. That skips the Set made from this array so it's only looking for items that exist in other arrays. That allows it to retain duplicates that occur in only one array.
Here's a version that uses the
Set
object if it's present, but inserts a teeny replacement if not (so this will work in more older browsers):