2

I am trying to split son array into chunks of 3 inner arrays.

ex:

[{
  title: "asd",
  description: "asd"
}, {
  title: "asz",
  description: "sd"
}, {
  title: "ws",
  description: "sd"
}, {
  title: "re",
  description: "sd"
}, {
  title: "32",
  description: "xxs"
}, {
  title: "xxc",
  description: "11"
}]

I want to convert upper son array into chunks like below

[
  [{
    title: "asd",
    description: "asd"
  }, {
    title: "asz",
    description: "sd"
  }, {
    title: "ws",
    description: "sd"
  }],
  [{
    title: "re",
    description: "sd"
  }, {
    title: "32",
    description: "xxs"
  }, {
    title: "xxc",
    description: "11"
  }]
]

I tried some sample like this but its working for this array ['a','b','c','d','e'] fine. below is the code I tried,

perChunk = 2 // items per chunk    

inputArray = ['a', 'b', 'c', 'd', 'e']

inputArray.reduce((resultArray, item, index) => {
  const chunkIndex = Math.floor(index / perChunk)

  if (!resultArray[chunkIndex]) {
    resultArray[chunkIndex] = [] // start a new chunk
  }

  resultArray[chunkIndex].push(item)

  console.log(resultArray)
  return resultArray

}, [])

But, for my input it's not working.

Please suggest me how can I achieve this

Aleksey Solovey
  • 4,153
  • 3
  • 15
  • 34
SFDC
  • 76
  • 2
  • 14
  • Your `perChunk` is `2`, yet the example clearly has `3` objects in each...? Also, this may help: https://stackoverflow.com/a/44069560/519413 – Rory McCrossan May 30 '18 at 08:33
  • The code you tried works for me, except that it splits into chunks with 2 items each instead of chunks with 3, because of your `perChunk = 2`. – CertainPerformance May 30 '18 at 08:34
  • What's your `expected output` when handling `leftover elements`? ie `array.length = 10` but `chunk size = 8` therefore `leftover elements = 2` – Arman Charan May 30 '18 at 09:06
  • I've added an update to my answer with usage of filter to remove empty objects from the array – Manoz May 30 '18 at 09:43

5 Answers5

3

Split the array into chunks of required size:

var arr = [{
  title: "asd",
  description: "asd"
}, {
  title: "asz",
  description: "sd"
}, {
  title: "ws",
  description: "sd"
}, {
  title: "re",
  description: "sd"
}, {
  title: "32",
  description: "xxs"
}, {
  title: "xxc",
  description: "11"
}]

var i, j, resArray=[], chunk = 2;
for (i = 0, j = arr.length; i < j; i += chunk) {
  resArray.push(arr.slice(i, i + chunk));
}

console.log(resArray);
Mamun
  • 66,969
  • 9
  • 47
  • 59
2

You can split array into given number of chunks

split(arr, n) {
        var res = [];
        while (arr.length) {
            res.push(arr.splice(0, n));
        }
        return res;
    }

Usage

 var arrayFregments = split(myArray, 3); //no of chunks
 var requests = arrayFregments.reduce((promiseChain, item) => {
            return promiseChain.then(() => new Promise((resolve) => {
                 asyncFunction(item, resolve); //some async function
            }));
        }, Promise.resolve());

 requests.then(() => {
               // after requests has been completed.
            });

Update

If you want to eliminate empty data object then you can use filter

mainList = mainList.filter(function(item){
        return item.title.trim().length>0 && item.description.trim().length>0

});
console.log(mainList)

Example - http://jsfiddle.net/zj1pe7q3/3/

Manoz
  • 6,507
  • 13
  • 68
  • 114
  • Thanks.. but I can't accept all the answers .. so I am really sorry – SFDC May 30 '18 at 08:47
  • @Basha, Nobody can't ;) – Manoz May 30 '18 at 08:47
  • Hi @Manoj small suggestion, how can I delete elements from array if element values have empty like title:"" and description:""... ex:[[{title:"a",desc:"ten"},{"title:"",desc:""}]]. here I want output as [[{title:"a",desc:"ten"]] .. any suggestion please – SFDC May 30 '18 at 08:56
  • you can filter array before processing into chunks. See here https://www.w3schools.com/jsref/jsref_filter.asp – Manoz May 30 '18 at 09:00
  • but, checking inner key value is possible in this mentioned w3schools url – SFDC May 30 '18 at 09:16
  • http://jsfiddle.net/mehbub/zj1pe7q3/2/ have a look in the fiddle and the last array element have empty title and empty description. I want to remove those before chunking – SFDC May 30 '18 at 09:32
  • http://jsfiddle.net/zj1pe7q3/3/ have a look at this, this is what I was talking about – Manoz May 30 '18 at 09:41
2

The following snippet splits arrays into chunks by size.

Array.prototype.filter() is used to omit unwanted elements (even numbers) from the input array.

Array.prototype.slice and a for statement are combined to create chunks without mutating the original input array.

Leftovers are included as a final chunk in the output, when relevant.

// Input.
const input = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(x => x % 2)

// Chunk.
const chunk = (array, size) => {
  let output = []
  let i = 0
  const max = array.length + (array.length % size) + 1
  for (let j = size; j < max; j += size) {
    output.push(array.slice(i, j))
    i = j
  }
  return output
}

// Output / Proof.
console.log('chunk size: 1', chunk(input, 1))
console.log('chunk size: 3', chunk(input, 3))
console.log('chunk size: 5', chunk(input, 5))
Arman Charan
  • 5,669
  • 2
  • 22
  • 32
  • Thanks I can't accept answer because I accepted some other one answer – SFDC May 30 '18 at 09:35
  • need small suggestion, jsfiddle.net/mehbub/zj1pe7q3/2 have a look in the fiddle and the last array element have empty title and empty description. I want to remove those before chunking – SFDC May 30 '18 at 09:36
  • [`.filter(({title, description}) => title && description)`](http://jsfiddle.net/ebpow1eo/) @Basha – Arman Charan May 30 '18 at 09:38
  • ^ See [`Destructuring Assignment`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) and [`Short-Circuit Evaluation`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Short-circuit_evaluation) for more info. – Arman Charan May 30 '18 at 09:43
1
// Chunk a single array into multiple arrays, each containing `count` or fewer
  // items.
function chunk(array, count) {
    if (count == null || count < 1) return [];
    var result = [];
    var i = 0, length = array.length;
    while (i < length) {
      result.push(Array.prototype.slice.call(array, i, i += count));
    }
    return result;
  };

Usage:

var newList = chunk(mainList, 2);

Demo Fiddle


OR

You can use chunk of underscore or lodash

var mainList = [
  {
    "title": "asd",
    "description": "asd"
  },
  {
    "title": "asz",
    "description": "sd"
  },
  {
    "title": "ws",
    "description": "sd"
  },
  {
    "title": "re",
    "description": "sd"
  },
  {
    "title": "32",
    "description": "xxs"
  },
  {
    "title": "xxc",
    "description": "11"
  }
];

var newList = _.chunk(mainList, 2);

Output:

[
  [
    {
      "title": "asd",
      "description": "asd"
    },
    {
      "title": "asz",
      "description": "sd"
    }
  ],
  [
    {
      "title": "ws",
      "description": "sd"
    },
    {
      "title": "re",
      "description": "sd"
    }
  ],
  [
    {
      "title": "32",
      "description": "xxs"
    },
    {
      "title": "xxc",
      "description": "11"
    }
  ]
]
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • Thanks.. but I can't accept all the answers .. so I am really sorry – SFDC May 30 '18 at 08:47
  • @Basha no worries mate :) – Maxim Shoustin May 30 '18 at 08:52
  • how can I delete elements from array if element values have empty like title:"" and description:""... ex:[[{title:"a",desc:"ten"},{"title:"",desc:""}]]. here I want output as [[{title:"a",desc:"ten"]] .. any suggestion please – SFDC May 30 '18 at 08:55
  • @Basha but u still want to make chunks of 2? – Maxim Shoustin May 30 '18 at 09:01
  • I got splitting into chunks. but, while saving I am saving as 3 chunks ... but throwing error because value is empty. So need to delete the array elements, if the title is empty – SFDC May 30 '18 at 09:04
  • Please take my demo in fiddle and reproduce your case there – Maxim Shoustin May 30 '18 at 09:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/172049/discussion-between-basha-and-maxim-shoustin). – SFDC May 30 '18 at 09:23
1

Try something like that:

const chucnk = (array, chunckSize) =>
  array.reduce(
    (a, b, i, g) =>
      !(i % chunckSize) ? a.concat([g.slice(i, i + chunckSize)]) : a,
    []
  );

const array = [{
  title: "asd",
  description: "asd"
}, {
  title: "asz",
  description: "sd"
}, {
  title: "ws",
  description: "sd"
}, {
  title: "re",
  description: "sd"
}, {
  title: "32",
  description: "xxs"
}, {
  title: "xxc",
  description: "11"
}]

chunck(array,3);
Nicolas Takashi
  • 1,550
  • 2
  • 10
  • 11