Stuck in Diff Two Arrays challenge

Tell us what’s happening:

OK, I tried solved this challenge for long time and can’t seem to figure out the problem. I do not get why I’m getting ‘Cannot read property ‘length’ of undefined’ error and removing length will return empty array. I also tried different approach as I comment out above but I will get the same error like the loop solution.

Your code so far


function diffArray(arr1, arr2) {

//var nomatch = arr1.filter(elem => !arr2.includes(elem));

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

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

Challenge: Diff Two Arrays

Link to the challenge:
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/diff-two-arrays

you need to do two things

  1. check the variables in your loop
  2. consider what happens if arr1 and arr2 have different length
1 Like
  1. Ohh… seems like I mix j with i.

  2. Not gonna lie. I don’t know what happens when arr1 and arr2 have different length. When I logged the failed tests, I notice that I get undefined inside the the first two array and I have a find a way to remove it. As for the third test, I have no idea what is happening here. But I do know one thing - tweaking this part (arr2[j]) < 0) might be the key to the solution.

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

console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));
console.log(diffArray([], ["snuffleupagus", "cookie monster", "elmo"]));
console.log(diffArray([1, "calf", 3, "piglet"], [7, "filly"]));

you have two cases:

  • arr2.length > arr1.length, and this mean that arr1[arr2.length] is undefined, and as undefined is not in arr2, it will be included in nomatch
  • arr2.length < arr1.length, this mean that arr1[arr2.length] has a value, but as j will not arrive at that value it will never be checked
1 Like

Alright, I’ll try to explain my thought-process as best as I can.

1. Understand the problem

I start by reading the problem multiple times and understand that what the challenge wants me to do is filter out the items in the array that did not match in arr1 and arr2. So for example, in arr1 has ['a','b','c'] and arr2 has ['a','b','c','d']. There is no 'd' item in arr1, so this item has to go to new array. This much I understood.

2. Draw the roadmap

Usually, I look at the hints to provide me some clues on how to design the path to the solution. The tests did not restrict what methods to use to solve so I’m free to use the one I’m most comfortable with - for loop. Based on the hints, it will go something like this:

/**
// Create a variable containing an empty array
// Create the loop to check if item in array1 is not equal to array2
// When the item is not equal to both arrays, push that item into a new empty array
// In the same loop, check if item in array2 is not equal to array1.
// Return the filtered array
*/

With this initially thought out plan, I’m going to split the problem and write pseudocodes.

3. Split the problem into small tasks and solve each task

At first, I was thinking of using filter() and worked out the examples from docs and blog post in Relp. Since I cannot think of a solution using the filter(), I decided to go with the for loop route.

This path may be longer than if I were to use high order function, but I can see the logical steps which I find it more important than writing less codes:

/**
// Create a variable containing an empty array
   variable no match = empty array
// Create the loop to check if item in array1 is not equal to array2
   for loop variable j 0, if j is less than 0, increment j
// When the item is not equal to both arrays, push that item into a new empty array
   if array1 item is not equal to array2, push item to variable no match
// In the same loop, check if item in arr2 is not equal to arr1.
   if array2 item is not equal to array1, push item to variable no match
// Return the filtered array
   return variable no match
*/

This should be fairly straightforward, at least to me. After logging the output so that I can see what the results would look like. I’m ready to write real codes.

4. Replace pseudocode with real codes

(Now this is the point where the problems starts to surface. It’s one thing to solve the logical problem through a pseudocode, it’s another thing when it’s time to implement it using real codes. You’ll see it shortly.)

For this challenge, how do I actually go on and check the items if it is not equal to array? What method do I have to use to compare the items against the arrays?

After googling, I figure out that I can do it using the == operator. I remember that I can use ! to see if the value is not equal to another value. Therefore in order to check it, I’d have to write if (arr2[j] !== arr1). I did the same thing in the second if statement by swapping arr2 with arr1.

Unfortunately, this returned not the way I expected. When I tweaked (arr2[j] !== arr1) into (arr2[j] !== 0), (arr2[j] !== -1) and so on, I get various results but not the one I am looking for.

When this happens, I often go back to read errors, change the codes, test it again, then check the docs, googling the errors, and so on.

At this point, I stopped to think logically and before I know it, I’m already powering through the problem with trial and error and this is how I end up the mess.

why in the same loop?

1 Like

To iterate the items of the arrays.

  • If there’s only if statement, then I won’t be iterate the second array.
  • If I create a nested for loop, It’d iterate the items more than once and that’s no good at all.

You know? Your question has made me to pause for a moment and ask myself why I’m pushing two arrays into an empty array when I could just concatenate them together and push it only once. I’ll try it now and see if this solve the problem.

but then how do you solve this issue?

1 Like

If arr2.length > arr1.length returns undefined and arr2.length < arr1.length will not be checked, then will this one arr2.length == arr1.length helps?

the issue was about the values that j get
your condition is j < arr2.length
what happens if arr1 and arr2 have different length?

this happen because j will have values of arr1.length and higher, and arr1[arr1.length] is undefined

the highest value that j can get is arr2.length-1 but arr1 has other values after that one, so arr1[arr2.length] and following values are never checked

if instead arr1.length == arr2.length then these issues do not exist, but notice from the tests that this do not happen often

1 Like

Okay, we have two arrays: arr1 containing ['a', 'b', 'd'] and arr2 containing ['a', 'c', 'e']. The goal is put an unmatched items from both arrays into a new array.

First, we’d have to access the arrays. When we get into arrays, we should try to access each item of the arrays. Once we do that, we should worry about comparing the items of each array against the other.

The next step to do after accessing both arrays and its items is to make comparison. If one item of the array is present in another array, we will leave it as it is. Otherwise, we will move that item from the origin array into the new empty array.

With that in mind, let’s compare the items, starting from arr1

  • Does item a in arr1 exist in arr2? Yes, we will leave it alone.
  • Does item b in arr1 exist in arr2? No, we will move it to a new array.
  • Does item d in arr1 exist in arr2? No, we will move it to a new array.

When we finish comparing it, our new array should be ['b','d']. Let’s do it again for arr2.

  • Does item a in arr2 exist in arr1? Yes, we will leave it alone.
  • Does item c in arr2 exist in arr1? No, we will move it to a new array.
  • Does item e in arr2 exist in arr1? No, we will move it to a new array.

And now, our new array should be like this ['b','d','c','e']. It looks a little different from ['b', 'c', 'd', 'e'] however it doesn’t look like that it has to be arranged in order.

that’s a good algorithm, why don’t you try to convert it to code? the steps should be exactly in the same order

1 Like

Yes, finally solve it!

So this is how I approach the coding problems. First, explain the logical steps as broad as possible using a plain English and not think about the codes. Second, when the logical steps sounds reasonable enough, convert it into the codes. Third (optionally) debug the codes.

function diffArray(arr1, arr2) {  
var nomatch = []
for (var i = 0; i < arr1.length; i++){
  if (arr2.indexOf(arr1[i]) == -1) {
  nomatch.push(arr1[i])
  }
}
for (var j = 0; j < arr2.length; j++){
  if (arr1.indexOf(arr2[j]) == -1) {
    nomatch.push(arr2[j])
  }
}
return nomatch
}
diffArray([1, "calf", 3, "piglet"], [7, "filly"]);

Thank you so much, @camperextraordinaire and @ilenia! I truly appreciate taking your time of the day to help me out. I’m going use this post as a reference to solve the rest of the challenges.

1 Like

at one point you were trying to solve this using filter, right? why don’t you try to that too?
solving the same algorithm in different ways is a good way to practice
you could also think of how to solve it in one line (note, it is a good exercise but not necessarily best practice)

1 Like

Good point. It’s worth trying it out now that I have a working solution.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.