Diff two arrays question about approach

Tell us what’s happening:
My plan was to use the .filter and .map methods for this problem. I wanted to filter out the parts of the array that match, and leave the ones that don’t. And use the map function to move through each part of the array when using the filter method. Is it possible to do it this way, or would you recommend a different approach?

Your code so far


function diffArray(arr1, arr2) {
var newArr = [];
newArr = arr1.concat(arr2);
let y = arr2.filter(item=>item != arr1.map(item=>item))
console.log(y)
}

diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36.

Challenge: Diff Two Arrays

Link to the challenge:

remember that map returns an array, so you are comparing a number with an array - it will not work, try changing way in which to check if the number is in the other array

So, I am trying to go by the hints of using concat and filter functions. I am having an issue with understanding why the filter function is not filtering out the items in the newest array that are present in both parameters.

function diffArray(arr1, arr2) {

var newArr = arr1.concat(arr2);

for (let i = 0; i < newArr.length; i++){

  newArr.filter(item => item === arr1[i] && item === arr2[i])

}console.log(newArr);

}

diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);

This is a symmetric difference problem which has 2 mathematical approaches:

  1. A Δ B = (A \ B) ⋃ (B \ A) Which technically means: The symmetric difference is equal to the difference between A and B --in union with-- the difference btween B and A. In code, this approach ensures that we don’t have to get rid of duplicates (since we’re not working with an actual Set data structure that gets rid of duplicates for us) although SOME duplicates may remain if one of the two arrays have duplicate items that may end up in the concatenated result.
  2. A Δ B = (A ⋃ B) \ (A ⋂ B) This means that the symmetric difference is equal to the difference between the union of A and B and the intersection of A and B. In code, this is more or less what most of us campers did when we solved this problem which means:
  • Concat A with B,
  • Then use filter on the result to get rid of elements present in BOTH A and B.
// Approach 2
A.concat(B)
  .filter(item => !(contains(item, A) && contains(item, B)));

// Approach 1
A.filter(item => !contains(item, B))
  .concat(
    B.filter(item => !contains(item, A))
  );

The predicate of approach 2 reads as

NOT (exists in A AND exists in B)

contains doesn’t exist in JS, so, read the rest of my message to find out exactly how to do it. Also, remember that ! is logical negation, it means “NOT”.

Your predicate (function inside filter) is wrong, first of all, what’s the point of using map/filter/reduce if you’re still using a for loop for indexing purposes? These methods provide a second (and third parameter that references the original array) argument to their callbacks that can be used as an index:

arr.iterativeMethod((item, index, originalArr) => {
  // ...
}, thisArg);

Secondly, this hardly matters in this particular case. What you can do instead is make use of the .indexOf array method that returns the index of an element in the array and if it doesn’t find it, returns -1.

Note that ES7 introduced the .includes method but that’s another story.

So basically you can implement it as:

/**
 * Predicate function that tells you whether
 * a particular value is present in an array.
 * @param {T} item - The element to find.
 * @param {T[]} arr - Where to find it.
 * @return {boolean} - The result of the search.
 */
function contains(item, arr) {
  return arr.indexOf(item) >= 0;
}
1 Like

I’m not a big fan of this approach. Seems like O(n^2) time complexity to me.

this was very helpful. Thank you for the advice!