15

Below is an array in which I have to group 3 values in each object:

var xyz = {"name": ["hi","hello","when","test","then","that","now"]};

Output should be below array:

[["hi","hello","when"],["test","then","that"],["now"]]
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Kalashir
  • 1,099
  • 4
  • 15
  • 38

8 Answers8

16

Pure javascript code:

function groupArr(data, n) {
    var group = [];
    for (var i = 0, j = 0; i < data.length; i++) {
        if (i >= n && i % n === 0)
            j++;
        group[j] = group[j] || [];
        group[j].push(data[i])
    }
    return group;
}

groupArr([1,2,3,4,5,6,7,8,9,10,11,12], 3);
stef
  • 14,172
  • 2
  • 48
  • 70
Avare Kodcu
  • 396
  • 6
  • 19
15

Here's a short and simple solution abusing the fact that .push always returns 1 (and 1 == true):

const arr = [0, 1, 2, 3, 4, 5, 6]
const n = 3

arr.reduce((r, e, i) =>
    (i % n ? r[r.length - 1].push(e) : r.push([e])) && r
, []); // => [[0, 1, 2], [3, 4, 5], [6]]

Plus, this one requires no libraries, in case someone is looking for a one-liner pure-JS solution.

Geza Kerecsenyi
  • 1,127
  • 10
  • 27
  • 2
    It's a clever and very useful solution that can be used as an expression and one can even use it to format currency with thousands separators when reversed and r.push([e]) becomes r.push([',',e]) ;) – Pete Jul 13 '21 at 20:00
  • Note 0 is a falsy value in JavaScript so this works without a comparison to 0. – Daniel Viglione Mar 14 '23 at 14:28
7

This can be covered by lodash _.chunk:

var xyz = {"name": ["hi","hello","when","test","then","that","now"]},size = 3;
console.log(_.chunk(xyz.name, size));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
4

You may use:

function groupBy(arr, n) {
  var group = [];
  for (var i = 0, end = arr.length / n; i < end; ++i)
    group.push(arr.slice(i * n, (i + 1) * n));
  return group;
}

console.log(groupBy([1, 2, 3, 4, 5, 6, 7, 8], 3));
gtournie
  • 4,143
  • 1
  • 21
  • 22
  • 1
    modifying the array your just iterating over is one of the oldest anti-patterns in programming.... – jebbie Jul 05 '19 at 08:20
  • 1
    What did you smoke @jebbie? I'm not modifying the array I'm iterating over! If you look closer, you'll see that I create a new array and then I add slices of the array passed in argument. `Array.prototype.slice` always returns a new array. IT NEVER MODIFIES IT. – gtournie Jul 16 '19 at 02:43
3

Hi please refer this https://plnkr.co/edit/3LBcBoM7UP6BZuOiorKe?p=preview. for refrence Split javascript array in chunks using underscore.js

using underscore you can do

JS

 var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.groupBy(data, function(element, index){
  return Math.floor(index/n);
});
lists = _.toArray(lists); //Added this to convert the returned object to an array.
console.log(lists);

or

Using the chain wrapper method you can combine the two statements as below:

var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.chain(data).groupBy(function(element, index){
  return Math.floor(index/n);
}).toArray()
.value();
Community
  • 1
  • 1
Gayathri Mohan
  • 2,924
  • 4
  • 19
  • 25
  • That's looks like the same answer given to this question (http://stackoverflow.com/questions/8566667/split-javascript-array-in-chunks-using-underscore-js) – Gruff Bunny Jun 27 '16 at 08:01
  • yeah i made reference also – Gayathri Mohan Jun 27 '16 at 08:02
  • @gayathri : I want to print that group in following structure . Can you help in that ?
    • a1a2a3
    • a4a5a6
    • a7a8a9
    – Kalashir Jun 27 '16 at 09:08
  • Instead of cutting and pasting the answer to the other question it would be more relevant to change it so that it applied to the data structure in this question. – Gruff Bunny Jun 27 '16 at 10:56
1

I ran into this same problem and came up with solution using vanilla js and recursion

const groupArr = (arr, size) => {
    let testArr = [];
    const createGroup = (arr, size) => {
        // base case
        if (arr.length <= size) {
            testArr.push(arr);
        } else {
            let group = arr.slice(0, size);
            let remainder = arr.slice(size);
            testArr.push(group);
            createGroup(remainder, size);
        }
    }
    createGroup(arr, size);
    return testArr;
}

let data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(groupArr(data, 3));
>>> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
1

Here is another simple oneliner, quite similar to the solution of gtournie.

  1. We create an array of the desired length array.length / n.
  2. We map portions of the initial array to the new array elements.
const group = (array, n) => 
  [...Array(Math.ceil(array.length / n))]
    .map((el, i) => array.slice(i * n, (i + 1) * n));
var xyz = {"name": ["hi","hello","when","test","then","that","now"]};
group(xyz.name, 3)

gives

[["hi","hello","when"],["test","then","that"],["now"]]
Anton
  • 1,045
  • 1
  • 7
  • 16
0

Here's a curry-able version that builds off Avare Kodcu's Answer.

function groupBy(groupSize,rtn,item,i)
{
    const j=Math.floor(i/groupSize)

    !rtn[j]?rtn[j]=[item]:
            rtn[j].push(item)

    return rtn
}

arrayOfWords.reduce(curry(groupBy,3),[])
Minifyre
  • 510
  • 2
  • 5
  • 17