2

I'm learning to code on freecodecamp at the moment and I'm tasked to complete a task. Here it is.

Create a function that takes two or more arrays and returns an array of the symmetric difference (△ or ⊕) of the provided arrays.

Given two sets (for example set A = {1, 2, 3} and set B = {2, 3, 4}), the mathematical term "symmetric difference" of two sets is the set of elements which are in either of the two sets, but not in both (A △ B = C = {1, 4}). For every additional symmetric difference you take (say on a set D = {2, 3}), you should get the set with elements which are in either of the two the sets but not both (C △ D = {1, 4} △ {2, 3} = {1, 2, 3, 4}).

What I have tried is to concat all the elements of the arguments object. I'm trying to use the native filter method to filter out elements in the array which have occured more than once. Here is what I have tried at the moment.

function sym() {
  let args = Array.prototype.slice.call(arguments);
  return args.reduce((prev,current) => prev.concat(current),[]) //concat all arguments
              .filter((element, index, array) => array.indexOf(element) !== index);
}

Can someone take a look and help me out? It would be much appreciated!

4 Answers4

1

You could filter first a and then b and concat the result.

function symetricalDifference(a, b) {
    function isNotInSet(set){
        return function (value) {
            return set.indexOf(value) === -1;
        }
    }

    return a.filter(isNotInSet(b)).concat(b.filter(isNotInSet(a)));
}

console.log(symetricalDifference([1, 2, 3], [2, 3, 4])); // [1, 4]
console.log(symetricalDifference([1, 4], [2, 3]));       // [1, 4, 2, 3]
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

I think this one will work for you.

function set() {
    let args = Array.prototype.slice.call(arguments);
    return args
        .reduce((prev, next) => prev.concat(next), [])
        .sort((a, b) => a - b)
        .filter( (el, i, array) => {
            if(i === 0) return true;
            if(el !== array[i-1]) {
                if(el !== array[i+1]) return true;
            }
        });
}

The logic is: first we need to concat all arrays into one and sort it so we have integers in ascending order something like this [1,2,2,3,4,5,5]. Then in this list of integers if some integer comes more than once then we have this in two or more of our original arrays, so we need to filter them out.

And results are:

set([1,2,3], [2,3,4]);
> [1,4]

And it works for more than two input arrays, as your task says:

Create a function that takes two or more arrays...

set([1,2,3], [2,3,4,11], [5,4,8]);
> [1,5,8,11]

Although, You should do type checking and other error handling stuff here.

Notice this only works for integers.

For sorting of an array of integers look here.

Hope this helps.

Community
  • 1
  • 1
sehrob
  • 1,034
  • 12
  • 24
0

console.log(sym([1, 2, 3], [5, 2, 1, 4]) )
function sym() {
 var count = {}
 for (var i=0; i<arguments.length; ++i) {
  arguments[i].forEach(function(v){
   if (!count[v]) count[v] = 1
   else ++count[v]
  })
 }
 return Object.keys(count).filter(function(k) {
  return count[k] === 1
 })
}
Hurelu
  • 1,458
  • 1
  • 14
  • 23
0

I suggest to

1) use filter and indexOf to find the list of duplicates, then

2) use filter and sort to return the final result as below:

function symmetricalDiff(a, b){
    var common = a.concat(b)
        .filter(function(d, index, inputArray){ 
            return inputArray.indexOf(d) != index
        });
    return (common.length==0) ? a.concat(b).sort() : 
        a.concat(b).filter(function(d){ return !common.includes(d)}).sort();
}
console.log(symmetricalDiff([1,2,3], [2,3,4]));  // [1, 4]
console.log(symmetricalDiff([1,4], [2,3]));       // [1, 4, 2, 3]
Dust Francis
  • 344
  • 3
  • 5