Skip to content Skip to sidebar Skip to footer

Finding Symmetric Difference/unique Elements In Multiple Arrays In Javascript

Hi I'm struggling to solve this problem. How to create a javascript function that takes any number of arrays as arguments, then returns an array of elements that only appear in one

Solution 1:

Here's one way to do it. The idea here is that you create a map for keeping counts of all the items in the array. You then cycle through each array, look up each value in the map and, if found, you increment its count. If not found, you set the count to 1. Then, when done with all the arrays, you collect any items that have a count of 1.

You weren't specific about what to do if an item appears more than once in the same array, but not in any other array. This first solution will not include that item (since it detects duplicates). It could be adapted (with a little more complexity) to allow that item if that was an issue (see 2nd code block below for that implementation).

function sym(/* pass one or more arrays here */) {
    var ans = [], cnts = {};

    //count all items in the array
    for (var i = 0; i < arguments.length; i++){
        arguments[i].forEach(function(item) {
            if (cnts.hasOwnProperty(item)) {
                // increase cnt
                ++cnts[item].cnt;
            } else {
                // initalize cnt and value
                cnts[item] = {cnt: 1, val: item};
            }
        });
    }
    for (var item in cnts) {
        if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
            ans.push(cnts[item].val);
        }
    }

    return ans;
}

If you want to include items that are present more than once in a single array, but not present in any other array, then you can use this slightly more complicated adaptation:

function sym(/* pass one or more arrays here */) {
    var ans = [], cnts = {}, currentMap;

    //count all items in the array
    for (var i = 0; i < arguments.length; i++){
        currentMap = {};
        arguments[i].forEach(function(item) {
            // if we haven't already counted this item in this array
            if (!currentMap.hasOwnProperty(item)) {
                if (cnts.hasOwnProperty(item)) {
                    // increase cnt
                    ++cnts[item].cnt;
                } else {
                    // initalize cnt and value
                    cnts[item] = {cnt: 1, val: item};
                }
            }
            // keep track of whethere we've already counted this item in this array
            currentMap[item] = true;
        });
    }
    // output all items that have a cnt of 1
    for (var item in cnts) {
        if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
            ans.push(cnts[item].val);
        }
    }

    return ans;
}

Working demo: http://jsfiddle.net/jfriend00/bete5k3n/


Solution 2:

I know this is increadibly late but this is another way to do it. Maybe not the most rigorous one but certainly creative. The method Array.symmetricDifference() expects any number of arguments and returns the symmetric difference of those arguments.

Array.prototype.symmetricDifference = function() {
  var args = [];

  // copy arguments into a real array and get rid of duplicates with filter
  for(var i = 0; i < arguments.length; i++) {
    args[i] = arguments[i];
    args[i] = args[i].filter(function(item, pos, self) {
      return self.indexOf(item) == pos;
    });
  }
  var diff = args[0];

  // iterate through every arguments in args.
  // concatenate the first two arguments to form a new set.
  // now every number in this new set that was contained in both arguments
  // from before will be contained at least twice in this new set.
  for(var j = 1; j < args.length; j++) {
    //sort the new set so that duplicates are next to each other.
    diff = diff.concat(args[j]).sort();
    var index = 0;

    // now iterate through the new set and delete both duplicates if you
    // find any. Otherwise proceed to the next index.
    while(index < diff.length) {
      // if duplicate is found delete both, otherwise look at next index.
      diff[index] === diff[index + 1] ? diff.splice(index, 2) : index++;
    }
  }
  return diff;
};

You can invoke that method on any array or create a new one and invoke it on that one like this for example:

// take any number of arrays
var a = [3, 3, 3, 2, 5];
var b = [2, 1, 5, 7];
var c = [3, 4, 6, 6];
var d = [1, 2, 3];
var e = [5, 3, 9, 8];
var f = [1];

// invoke the method on "solution" with any number of arguments
// and store it in solution.
var solution = solution.symmetricDifference(a,b,c,d,e,f);

console.log(solution); // [1, 2, 4, 5, 6, 7, 8, 9]

I hope this helps!


Solution 3:

Finding unique items in multiple arrays

function uniqueItemsInArrays(...args){
  let allItems = [];
  allItems = allItems.concat(...args)

  return allItems.filter(function(item, pos, self) {
         return self.indexOf(item) === pos && self.indexOf(item,pos+1) === -1;
  });
}

uniqueItemsInArrays( [1, 5, 1, 8, 1, 2],
                         [2, 2, 9, 3, 5],
                         [1, 4, 7, 6] );

The above code uses ES6 rest parameters to access all the arrays passed as arguments. Then using the concat() function, I am joining all the individual arrays to a single array. Finally, filter function has been used to identify and return the unique items from this array. The logic here is to find out the first index of the current item and if there are no more occurrence from the first index then we return that item.


Post a Comment for "Finding Symmetric Difference/unique Elements In Multiple Arrays In Javascript"