1

OBJECTIVE

I am trying to highlight the dfferences between two arrays. Please note that arr1 and arr2 will vary in length and have multiple types present (strings and numbers).

MY CODE

function diff(arr1, arr2) {
  var diffArr = [];

  if (arr1.length >= arr2.length) {
    for (var i = 0; i < arr1.length; i++){
      if (arr2.indexOf(arr1[i]) < 0) {
          diffArr.push(arr1[i]);
          }
    }
  } else {
    for (var j = 0; j < arr2.length; j++){
      if (arr1.indexOf(arr2[j]) < 0) {
        diffArr.push(arr2[j]);
      }
    }
  }
  return diffArr;
}

ISSUES

diff([1, 2, 'cat', 'fish'], [1, 2, 3,'dog']); //returns only ['cat', 'fish']

I am pretty sure that my code is only returning the duplicates in one of the arrays via diffArr.push (even if there are unique values in both arrays). However, I am unsure how to overcome this.

My references

Removes Duplicates from Javascript Arrays

Removed Duplicates from an Array Quickly

Javascript Array Difference

jonplaca
  • 797
  • 4
  • 16
  • 34
  • @Donal I dont think that this is true - indexOf() can be used for arrays (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) – jonplaca May 25 '15 at 17:22

2 Answers2

2

Your code currently only crawls through one array (let's call it A) and pushes in all the A values that don't exist in B. You never go the other way and push in the B values that don't exist in A. There's also no need to have different behavior based on which array is longer. Here is the final answer in a simple way:

function diff(arr1, arr2) {
  var diffArr = [];
  for (var i = 0; i < arr1.length; i++) {
    if (arr2.indexOf(arr1[i]) < 0) diffArr.push(arr1[i]);
  }
  for (var j = 0; j < arr2.length; j++) {
    if (arr1.indexOf(arr2[j]) < 0) diffArr.push(arr2[j]);
  }
  return diffArr;
}

And in a slightly more functional way:

function diff(arr1, arr2) {
  var elsIn1Not2 = arr1.filter(function(el){ return arr2.indexOf(el) < 0; });
  var elsIn2Not1 = arr2.filter(function(el){ return arr1.indexOf(el) < 0; });
  return elsIn1Not2.concat(elsIn2Not1);
}

Both functions return [ 'cat', 'fish', 3, 'dog' ] for your example.

Gabriel L.
  • 1,629
  • 1
  • 17
  • 18
  • Thank you for this - I've been struggling with developing a more functional way of programming. I've been having trouble specifically with .filter() (the MDN example isn't great). Upvoted and labeled as the correct answer! – jonplaca May 26 '15 at 18:06
  • Thanks. :-) If you really want to make it concise, you could change `return arr2.indexOf(el) < 0;` to `return !~arr2.indexOf(el`. ;-) That might just be the only mainstream use of the `~` operator (bitwise NOT)… – Gabriel L. Jun 03 '15 at 04:33
0
function diff(arr1, arr2) {
  var diffArr = {};

  if (arr1.length >= arr2.length) {
    for (var i = 0; i < arr1.length; i++){
      if (arr2.indexOf(arr1[i]) < 0) {
          diffArr[arr1[i]] = 1;
          }
    }
  } else {
    for (var j = 0; j < arr2.length; j++){
      if (arr1.indexOf(arr2[j]) < 0) {
        diffArr[arr2[j]] = 2;
      }
    }
  }
  return diffArr.keys();
}
skazska
  • 421
  • 2
  • 8
  • This doesn't solve the author's question, which seems to be "how can I get an array of all the elements not shared by both arrays." If you keep that if-else, then you'll only ever get a one-way diff. – Gabriel L. May 25 '15 at 17:59