3

I am expected to write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a two-dimensional array. Therefore, chunkArrayInGroups(["a", "b", "c", "d"], 2) should return [["a", "b"], ["c", "d"]]

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var result=[];
  for (var i=0;i<=Math.ceil(arr.length/size);i++){

      var j=0;
      if(i!== 0){
        j+=size;
        size+=size;
      }

      result[i] = arr.slice(j , size);  

  }
  //return arr.length/size 
  //results in 1.5

return result;
// results [["a", "b"], ["c", "d"]]


}

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

I am getting the desired result but I'm not very satisfied with my solution, also, more importantly "if" arr.length = 4; and, size =2; then why is arr.length/size = 1 ? shouldn't it be 4/2=2?

  • _"more importantly why is arr.length = 4"_ Original array `arr` is not affected due to use of `.slice()` at `result[i] = arr.slice(j , size);` Is requirement to change original array? – guest271314 Jun 05 '16 at 16:31
  • Possible duplicate of [Split array into chunks](http://stackoverflow.com/questions/8495687/split-array-into-chunks) – matsev May 05 '17 at 19:54

9 Answers9

3

I would make i iterate the indices in the original array where each group begins, instead of the indices of the groups.

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

And also consider a generator:

function* chunkArrayInGroups(arr, size) {
  for (var i=0; i<arr.length; i+=size)
    yield arr.slice(i, i+size);
}
Oriol
  • 225,583
  • 46
  • 371
  • 457
  • what is a generator? also, `yield`? is it used interchangeably with `return`? –  Jun 05 '16 at 16:50
  • 1
    @Rashid [What is “function*” in JavaScript?](http://stackoverflow.com/q/9620586/1529630), [What's the yield keyword in JavaScript?](http://stackoverflow.com/q/2282140/1529630) – Oriol Jun 05 '16 at 16:53
2

You modify size inside the loop. This basically doubles the size at every step. The fact that your example only has two sub-arrays hides this problem. Try larger arrays to see the problem in the result.

To fix this, declare j outside of the loop. Add the size to j after slicing.

Edit: Code, as requested

function chunkArrayInGroups(arr, size) {
  var result = [];
  var j = 0;
  for (var i = 0; i < Math.ceil(arr.length / size); i++) {
    result[i] = arr.slice(j, j + size);
    j = j + size;
  }
  return result;
}

Or, slightly simplified:

function chunkArrayInGroups(arr, size) {
  let result = [];
  let pos = 0;
  while (pos < arr.length) {
    result.push(arr.slice(pos, pos + size));
    pos += size;
  }
  return result;
}
Stefan Haustein
  • 17,024
  • 3
  • 30
  • 45
1

You can use reduce() with slice()

function chunkArrayInGroups(ar, num) {
  return ar.reduce(function(r, v, i) {
    if (i % num == 0) r.push(ar.slice(i, i + num));
    return r;
  }, []);
}

console.log(chunkArrayInGroups(["a", "b", "c", "d"], 2))
Nenad Vracar
  • 102,378
  • 14
  • 116
  • 136
1

The following solution works quite well:

function chunkv2(arr,size) {
    var result = [];
    for(var i = 0; i < arr.length; i++) {
        if(i%size === 0)
            // Push a new array containing the current value to the result array 
            result.push([arr[i]]);
        else
            // Push the current value to the current array
            result[result.length-1].push(arr[i]);
    }
    return result;

}

It works by using the modulus operator to see if it should create a new array.

Lukas Gjetting
  • 175
  • 1
  • 10
0

more importantly why is arr.length = 4

Original array arr is not affected within chunkArrayInGroups due to use of .slice() at

result[i] = arr.slice(j , size)
guest271314
  • 1
  • 10
  • 82
  • 156
  • @Rashid _"what do you think of my code?is it very weak?"_ Did not review `js` at original post in that manner. Only reviewed OP as to actual Question presented: _"more importantly why is arr.length = 4"_ – guest271314 Jun 05 '16 at 16:43
  • I think you got me wrong , My question is "if" arr.length = 4; and, size =2; then why is arr.length/size = 1.5 ?shouldn't it be 4/2=2? –  Jun 05 '16 at 16:43
  • @Rashid _"then why is arr.length/size = 1.5 "_ Where did you get a value of `1.5`? `size` is changed within `for` loop at `size+=size;` – guest271314 Jun 05 '16 at 16:45
  • @Rashid Not certain how you retrieved the value `1.5` from `arr.length/size`? – guest271314 Jun 05 '16 at 16:53
  • sorry, my bad..its 1 –  Jun 05 '16 at 16:57
0

here is what i came up with:

function divyArray(input,size){
    var output = [];
    for(var i = 0;i<input.length;i){
        var chunk = [];
        for(var j = 0;j<size;j++){
            chunk.push(input[i]);
            i++;
        }
        output.push(chunk);
    }
    return output;
}
Johnathan Ralls
  • 121
  • 1
  • 12
  • 1
    my opinion is you have too much processing going on, for large bits of data you're doing extra work. all that is needed to to use the variables you create as much as you can! here i have output, i, j, and chunk. with that i don't need to do anything but increment and test against size or length – Johnathan Ralls Jun 05 '16 at 16:40
0

A way to simplify it could look something like this:

    function chunkArrayInGroups(arr, size) {
    var result=[], j=0, divisions = arr.length/size;

    if (divisions % size != 0) { 
       console.log("Array of length"+ arr.length +"is undividable by "+divisions);
    }
    for (var i=0;i<=divisions-1;i++){
        result[i] = arr.slice(j , size);  console.log(result[i]);
        j+=size;
        size+=size;
    }
    return result;
}

You might want to add some error logic for undividable arrays or alternate methods if you want to divide them differently but this is close to how it was before with a few changes. I'm not sure how you're getting 1.5 for arr.length/size- I'm getting the correct number for this.

Anders Elmgren
  • 551
  • 4
  • 8
0

I guess it doesn't get any better than a total reducing solution lets do it;

var arr = ["a", "b", "c", "d"],
      g = 2,
    res = arr.reduce((p,c,i) =>  !(i%g) ? p.concat([[c]]) : (p[p.length-1].push(c),p),[]);
console.log(res);
Redu
  • 19,106
  • 4
  • 44
  • 59
-1

You could use a method without slice.

function chunkArrayInGroups(array, size) {
    return array.reduce(function (r, a, i) {
        var p = Math.floor(i / size);
        r[p] = r[p] || [];
        r[p].push(a);
        return r;
    }, []);
}
  
console.log(chunkArrayInGroups(["a", "b", "c", "d"], 2));
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324