1

I'm writing a diff(arr1, arr2) function to compare two arrays and return a new array with any items not found in both of the original arrays.

Example:

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]) 
// [4]

diff([1, "calf", 3, "piglet"], [7, "filly"])
// [1, "calf", 3, "piglet", 7, "filly"]

My solution is to build an object using the unique value in the array as the key, and the frequency as the value to that key. Then I collect the key whose value is 1 into a new array.

Problem: I think the fact that key is treated as a string in object makes my solution not very elegant, because I will need to use Number() to convert an "integer" key from string to number.

Question: my code works but does anyone have a better solution to find unique values after comparing 2 arrays?

My code:

function diff(arr1, arr2) {

  var newArr = arr1.concat(arr2);
  var dict = {};

  for (var i = 0; i < newArr.length; i++) {
    if (!dict[newArr[i]]) {
      dict[newArr[i]] = 1;
    }
    else {
      dict[newArr[i]]++;
    } 

  }

  var unique = [];

  for (var key in dict) {
    if (dict[key] === 1) {
      if (!Number(key)) {
        unique.push(key);
      }
      else {
        unique.push(Number(key));
      }
    }
  }
  return unique;
}

Thanks for your help =)

Neong
  • 53
  • 1
  • 11

4 Answers4

2

You can implement diff function like the following, if you can use underscore.js.

function diff (arr1, arr2) {
  return _.difference(arr1, arr2).concat(_.difference(arr2, arr1));
}
ntalbs
  • 28,700
  • 8
  • 66
  • 83
2

Leaving aside issues of performance, this can be written as:

function complement(a1, a2) { return a1.filter(v => !a2.includes(v)); }
function union     (a1, a2) { return a1.concat(a2); }

function difference(a1, a2) { return union( complement(a1, a2), complement(a2, a1) ); }

You'll need an environment that supports Array#includes, or a polyfill, or write it yourself:

function complement(a1, a2) { return a1.filter(v => a2.indexOf(v) === -1); }
1

Here is a pure JS solution:

var diff = function(array1, array2) {
    var simmetricDifference = [];

    var getMissedItems = function(sourceArray, searchInArray) {
        sourceArray.forEach(function(item) {
            if((searchInArray.indexOf(item) === -1) && (simmetricDifference.indexOf(item) === -1)) {
                simmetricDifference.push(item);
            }
        });
    };

    getMissedItems(array1, array2);
    getMissedItems(array2, array1);

    return simmetricDifference;
};
Alexander Elgin
  • 6,796
  • 4
  • 40
  • 50
  • The formal definition of symmetric difference is that it will not remove duplicate elements in one of the arrays. –  Oct 30 '15 at 07:18
1

the question is actually referring to symmetric difference function. Use _.xor.

kornieff
  • 2,389
  • 19
  • 29
  • Think you should add the `_.xor` is not native Javascript but a method from one of several frameworks/libraries. – Blindman67 Oct 30 '15 at 07:01