# Chunky Monkey

## Problem Explanation

Our goal for this Algorithm is to split `arr` (first argument) into smaller chunks of arrays with the length provided by `size` (second argument). There are 4 green checks (objectives) our code needs to pass in order to complete this Algorithm:

1. `(['a', 'b', 'c', 'd'], 2)` is expected to be `[['a', 'b'], ['c', 'd']]`
2. `([0, 1, 2, 3, 4, 5], 3)` is expected to be `[[0, 1, 2], [3, 4, 5]]`
3. `([0, 1, 2, 3, 4, 5], 2)` is expected to be `[[0, 1], [2, 3], [4, 5]]`
4. `([0, 1, 2, 3, 4, 5], 4)` is expected to be `[[0, 1, 2, 3], [4, 5]]`

## Hints

### Hint 1

The links above suggest to use `Array.push()`, so letâs start by first creating a new array to store the smaller arrays we will soon have like this:

``````var newArray = [];
``````

### Hint 2

Next weâll need a `for loop` to loop through `arr`.

### Hint 3

Finally, we need a method to do the actual splitting and we can use `Array.slice()` to do that. The key to this Algorithm is understanding how a `for loop`, `size`, `Array.slice()` and `Array.push()` all work together.

## Solutions

Solution 1 (Click to Show/Hide)
``````function chunkArrayInGroups(arr, size) {
let temp = [];
const result = [];

for (let a = 0; a < arr.length; a++) {
if (a % size !== size - 1) temp.push(arr[a]);
else {
temp.push(arr[a]);
result.push(temp);
temp = [];
}
}

if (temp.length !== 0) result.push(temp);
return result;
}
``````

#### Code Explanation

• Firstly, we create two empty arrays called `temp` and `result`, which we will eventually return.
• Our for loop loops until `a` is equal to or more than the length of the array in our test.
• Inside our loop, we push to `temp` using `temp.push(arr[a]);` if the remainder of `a / size` is not equal to `size - 1`.
• Otherwise, we push to `temp`, push `temp` to the `result` variable and reset `temp` to an empty array.
• Next, if `temp` isnât an empty array, we push it to `result`.
• Finally, we return the value of `result`.

Solution 2 (Click to Show/Hide)
``````function chunkArrayInGroups(arr, size) {
// Break it up.
const newArr = [];
for (let i = 0; i < arr.length; i += size) {
newArr.push(arr.slice(i, i + size));
}
return newArr;
}
``````

#### Code Explanation

• First, we create an empty array `newArr` where we will store our âchunksâ.
• The for loop starts at zero, increments by `size` each time through the loop, and stops when it reaches `arr.length`.
• Note we are using the loop to generate numbers we can use as indices to slice the array in the right locations.
• Inside our loop, we create each chunk using `arr.slice(i, i+size)`. The `slice` method accepts two arguments with the first argument being the index of where the slice should start and the second argument being where the slice should end but does not include the ending index.
• We add this chunk/slice to `newArr` with `newArr.push()`.
• Finally, we return the value of `newArr` once the for loop is complete.

Solution 3 (Click to Show/Hide)
``````function chunkArrayInGroups(arr, size) {
// Break it up.
const newArr = [];
let i = 0;

while (i < arr.length) {
newArr.push(arr.slice(i, i + size));
i += size;
}
return newArr;
}
chunkArrayInGroups(["a", "b", "c", "d"], 2);
``````

#### Code Explanation

• Firstly, we create two variables. `newArr` is an empty array which we will push to. We also have the `i` variable set to zero, for use in our while loop.

• Our while loop loops until `i` is equal to or more than the length of the array in our test.

• Inside our loop, we push to the `newArr` array using `arr.slice(i, i+size)`. For the first time it loops, it will look something like:

newArr.push(arr.slice(1, 1+2))

• After we push to `newArr`, we add the variable of `size` onto `i`.

• Finally, we return the value of `newArr`.

Solution 4 (Click to Show/Hide)
``````function chunkArrayInGroups(arr, size) {
const newArr = [];
while (arr.length > 0) {
newArr.push(arr.splice(0, size));
}
return newArr;
}
``````

#### Code Explanation

• Firstly, we create a variable. `newArr` is an empty array which we will push to.
• Our `while` loop loops until the length of the array in our test is not 0.
• Inside our loop, we push to the `newArr` array using `arr.splice(0, size)`.
• For each iteration of `while` loop, it deletes `size` number of elements from the front of `arr` and push them as an array to `newArr`.
• Finally, we return the value of `newArr`.

Solution 5 (Click to Show/Hide)
``````function chunkArrayInGroups(arr, size) {
if (arr.length <= size) {
return [arr];
} else {
return [arr.slice(0, size)].concat(
chunkArrayInGroups(arr.slice(size), size)
);
}
}
``````

#### Code Explanation

• Array smaller than size is returned nested.
• For any array larger than size, it is split in two. First segment is nested and concatenated with second segment which makes a recursive call.

127 Likes

Itâs important to see if any of those solutions doesnât hang up when the size passed is 0 or less, which may cause an infinite loop.

13 Likes

Why is the while loop the advanced solution? I had the intermediate one and to me itâs easier to read. Is it because while loops are faster? If so, is the difference significant?

9 Likes

@Naqin I donât understand it either, I came up with this:

``````function chunkArrayInGroups(arr, size) {
var newArr = [];
var index = 0;

while (index < arr.length){
newArr.push(arr.slice(index,index+size));
index += size;
}

return newArr;
}
``````

Which I suppose is the advanced one, but afterwards I thought that I could have optimized it further for readability, if I did, I would have ended with the `for` intermediate solution, but in the end I didnât as it doesnât seem to be much of a difference âŚ

So Iâm also wondering which one is faster in this situation, `for` or `while`.

11 Likes

I know in C#.Net For Loops are faster than While and ForâŚIn Loops.

Here is a the runs performance tests for array loops, Fastest array loops in Javascript.

The website indicates having the `array.length` in a variable like `len` is faster than a normal For Loop.

### Below listed in order of fastest

For loop, i -= 1 II

``````var i;
for (i = arr.length; i > 0; i -= 1) {
someFn(i);
}
``````

For loop, cached

``````for (var i = 0, len = arr.length; i < len; i++) {
someFn(i);
}
``````

For loop, basic

``````for (var i = 0; i < arr.length; i++) {
someFn(i);
}
``````
3 Likes

My first recursive algorithm. Iâm beaming with joy.

``````function chunkArrayInGroups(arr, size) {
// Break it up.
var mArr = [];

function newChunks (arr, size, mArr){
if (arr.length > 0 ){
mArr.push(arr.splice(0, size));
newChunks(arr, size, mArr);
}

}
newChunks(arr, size, mArr);
return mArr;
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 3);``````
13 Likes

@Naqin I donât think it has to do with the while loop. I think it may have something to do with the fact that the solution is using the .splice() method, which alters the original array. Unless you know exactly what you are doing it is kind of risky to alter the array while you are using it.

Just my thoughts

1 Like

I came up with

``````function chunkArrayInGroups(arr, size) {

var result = [];

for (var i=0; i<arr.length/size; i++){
result.push(arr.slice(size*i, size*(i+1)));
}
return result;
}
``````

is there any reason why this would be a bad code?

24 Likes

This worked for me. Feedback, anyone?

``````function chunkArrayInGroups(arr, size) {
newArr = [];
var stop = size;
for(var i = 0; i < arr.length; i += size) {
newArr.push(arr.slice(i, stop));
stop += size;
}
return newArr;
}

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

wow nice solution! why did you call newChunks again down at the bottom?

The first time you see function newChunks, Iâm declaring the function. Inside the function newChunks I then call it inside itself so it automatically repeats (the recursion). Basically you are saying do function newChunks and then do it again indefinitely. This is why you need a condition in the function so it doesnât go on forever.

Then finally at the bottom, I am actually calling the function for the first time so it runs.

2 Likes

For cycle without cycleâs variable increment/decrement

``````function chunkArrayInGroups(arr, size) {
var ar = [];
for (i = 0; i < arr.length;) ar.push(arr.splice(i, size));
return ar;
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4);
``````
14 Likes

Hey lbarjak, I know the final-expression in a for statement is optional, but how does the loop know to continue incrementing or updating the counter variable?

1 Like

The variable is arr.length only. I use splice instead slice.

``````const chunkArrayInGroups = (arr, size) =>
[...Array(Math.ceil(arr.length / size))].map((val, i) =>
arr.slice(i * size, (i + 1) * size));
``````
11 Likes
``````// Using splice.
// Found splice very useful in this case.
function chunkArrayInGroups(arr, size) {
// Break it up.
var arr1=[];
while (arr.length>0) {
arr1.push (arr.splice(0,size));
}
return arr1;
}

chunkArrayInGroups(["a", "b", "c", "d", "e"], 3);``````
6 Likes
``````// Another solution, pretty exhaustive:
function chunkArrayInGroups(arr, size) {
// Break it up.
var arr1=[];
var tempSize=0;
var tempArr=[];
while (arr.length>0) {
tempArr.push(arr.shift());
tempSize++;
if (tempSize===size) {
arr1.push(tempArr);
tempSize=0;
tempArr=[];
} else if (arr.length===0) {
arr1.push (tempArr);
}
}
return arr1;
}

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

i managed to solve this by

function chunkArrayInGroups(arr, size) {
var result = [];
if (size <= 0){