Diff Two Arrays using some() and forEach()

Tell us what’s happening:
Can someone help me determine why I am printing the exact opposite of my intentions to the console?

console prints “[ 1, 2, 3, 5 ]”
I expected it to print just “[4]” since I used “!==”.

Thanks in advance.

Edit: I just realized I am only pushing values from arr1 and that I will also need to push from arr2 at some point. but I am still confused why 1, 2, 3, 5 are printing.

Your code so far


function diffArray(arr1, arr2) {
let newArr = [];

function myReturn (item){
  return item
}

//Use some() to find if any values in arr1 are different.
arr1.some(test)

//Use forEach() to call all of arr2
function test(value){
if (value !== arr2.forEach(myReturn)){
//should push different values to newArr
  newArr.push(value)
}
}
console.log(newArr);
//return newArr;
}

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/87.0.4280.66 Safari/537.36.

Challenge: Diff Two Arrays

Link to the challenge:

Hi @jordan.werts. The callback to Array.prototype.some should return a boolean value.

The task is to diff two arrays. Is there any reason why you chose to use some and forEach?

from the w3 schools page for some:

If it finds an array element where the function returns a true value, some() returns true (and does not check the remaining values)

I don’t think this is the approach you want to go with.

Hello Jordan. First of all, Array.prototype.forEach does not return anything, never. You need a function like .map() or .reduce() to do so. ForEach does perform a function on each element, but without returning; therefore, if you want to transform an array in-place (this way you lose the original) you can use map/reduce. A forEach is not much different from a for…in loop. You can run it and check for a condition and then choose to do something with the element, like pushing it to an array, but you will never return; in other words, there is no way to break the loop.

Second thing. Even if we’d use map instead of the current forEach, your callback function myReturn does… nothing… it simply returns the element, it leaves it as it is now.

That said, lets look at a possible solution using forEach and some

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2) //first off, we merge the two array together
  var uniqueArray = []; //this is the array of unique elements we'll return
//iterate through our merged arrays
  newArr.forEach(element => {
 //now, for every element, you check if it missing from one of the two arrays
//in pseudocode this will be like:
    if(!arr1.some(el => el == element) || !arr2.some(el => el == element)){
 //              ^-- is the current element missing from array 1?
//       OR
//                                   is  missing from array 2?--^
       uniqueArray.push(element) //if it's missing somewhere, we have a unique value; push it to our  array of unique elements
    }
  })
  return uniqueArray
}

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

You have many options here, like using filter, reduce ecc, so try them out…

Thanks, everyone. I’m going to start over and look at map/reduce, as @doriodavid recommended, to see if I can come up with a better way to approach the challenge.

1 Like

So I started over, combined the arrays, and was struggling with getting two arrays into my filter. After some googling, I copied some similar code and changed a few values to meet my needs and it worked!

The trouble is it worked before I fully understood what was happening. Can someone help explain why…

  1. there is an _ in the middle of the filter input.

  2. At the end of the return statement there is a “.length === 1” . This part just lost me. how can you put a . length here and why does it need to be strictly = to 1?

function diffArray(arr1, arr2) {
  var newArr = [];
  const combine = [...arr1, ...arr2];
  
  var result = combine.filter((value, _, arr) => {
    
          return arr.filter(value2 => value2 === value).length === 1
})
  console.log(result)
 
  
  
  return result;
}

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

That underscore is just a “placeholder” for an unused parameter. The .filter callback function takes 3 parameters, in that order:

  • the current value (named value in your code)
  • the current array index (normally called i, in your code it’s an underscore to indicate that it’s not used anywhere)
  • the array itself (named arr)

The combined array that you’re looping over with .filter is:

[1, 2, 3, 5, 1, 2, 3, 4, 5]

With that check .length === 1, you only let items pass that are present exactly once in the array, so here the output is

[4]

If you change the code to .length === 2, the output would be:

[1, 2, 3, 5, 1, 2, 3, 5]