Chunky Monkey (Cannot Read Property '0' of undefined)

Tell us what’s happening:

I am getting the error of cannot read property ‘0’ of undefined. I have tried googling for the error, and it seems to occur when a program tries to reach an out of bounds index in an array. However, I am not sure which part of my code is causing this.

Your code so far


function chunkArrayInGroups(arr, size) {
  // Break it up.
let newArr = [];
let x = 0;

for(let i = 0; i < (arr.length)/size; i++){
  for(let j = 0; j < size; j++){
      newArr[i][j].push(arr[x]);
      x++;
    }  
  }
return newArr;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2); 


Your browser information:

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

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-algorithm-scripting/chunky-monkey

It happens because in your second loop, the j might go out of bounds. For example if you have 7 elements in the array, and the size is 3, the third time the index would go beyond the array’s length.

Also as a quick advice, instead of having this: let i = 0; i < (arr.length)/size; i++, you could increment i by the size value, and go up to arr.length

Hi Flopet,

Thanks for the quick response. I agree that this code is unable to capture events ifarr.length % size != 0.

However, I fail to see in this case, if the arguments are ["a", "b", "c", "d"], 2, then arr.length/size = 2 and size = 2 (i.e arr.length % size ==0) why would it still become out of bounds?

I would imagine the last element pushed into newArr would be newArr[1][1] = arr[3].

Appreciate your clarification! Thanks.

My bad. I just noticed the error. You have the newArr set to be an array, but it doesn’t know what newArr[0][0] is, as you don’t have an inner array.

Try pushing a new array before the 2nd loop: newArr[i].push([])

I tried doing this but I got the error:

“Cannot read property ‘push’ of undefined”

Here’s the code:

function chunkArrayInGroups(arr, size) {
  // Break it up.
var newArr = [];
let x = 0;

for(let i = 0; i < (arr.length)/size; i++){
  newArr[i].push([]);
  for(let j = 0; j < size; j++){
      newArr[i][j].push(arr[0]);
    }  
  }
}

chunkArrayInGroups(["a", "b", "c", "d"], 2); 

The issue is that you have declared newArr as an empty array, but in your loop you are trying to push
in int, but you can’t push into something that is undefined.

var newArr = [];

// i = 0 || newArr[0] -> undefined
newArr[i].push([]);

However remember that you can declare variables that are local to each loop iteration. :slight_smile:
hope it helps

1 Like

I spent a little time to create an example. Hope this is helpful.

function chunkArrayInGroups(arr, size) {
  let newArr = [];
  let x = 0;
  let y = 0;
  for(let i=0; i<arr.length; i+=size) {
    newArr.push([]);
    for(let j=0; j<size; j++) {
      if(arr[x] !== undefined) {
        newArr[y].push(arr[x]);
        x++; 
      }
    }
    y++;
  }
  return newArr;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

I used x to go through all thearr items and y to increment for each inner array (when j reaches to the size value).

Also, as you can see, in the first loop we increment by the size, and in the inner loop, we go through those elements that are within the ranges.

1 Like

your solution is here

function chunkArrayInGroups(arr, size) {
  // Break it up.
   var matrix = [], i, k;

    for (i = 0, k = -1; i < arr.length; i++) {
        if (i % size === 0) {
            k++;
            matrix[k] = [];
        }

        matrix[k].push(arr[i]);
    }

    return matrix;
}

2 Likes

@freecodecampram @Flopet17 perhaps mark your solutions as spoilers, so that @cornstar94 still have a chance to come with a solution by himself and resort to looking at other people’s code as last chance :wink:

p.s. if you want to see a more functional approach that doesn’t involve a for loop :slight_smile:

const chunkArray = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);

1 Like

appreciate your step :drooling_face: but it make me more happy at least if you given me an upvote.

Thanks for taking the time to work through the solution. I think I am beginning to grasp where my error lies.

I assumed that newArr[i][j] exists so long as I pushed a value into it. I am not sure how I got the impression that this would work from the prior exercises.

But I realised that I need to initialise/define the sub-array by performing newArr.push([]).

If I didn’t do that, newArr[i][j] would be undefined as mentioned by @Marmiz.

I also found this link (https://www.sitepoint.com/community/t/typeerror-myarray-j-is-undefined/190412/11) useful in helping me understand this. Thank you everyone for your help!

Building on my earlier code, and the suggested improvements: here’s my final code:

function chunkArrayInGroups(arr, size) {
  // Break it up.
let newArr = [];
let x = 0;

for(let i = 0; i < (arr.length)/size; i++){
  newArr.push([]);
  for(let j = 0; j < size; j++){
    if(x < arr.length){
      newArr[i].push(arr[x]);
      x++;   
    }  
  }
} 
console.log(newArr);
  return newArr; 
}
chunkArrayInGroups([0, 1, 2, 3, 4, 5], 4);
1 Like