Home > database >  How to split nested array into "rows" with limited size
How to split nested array into "rows" with limited size

Time:02-24

I have an array of arrays of different sizes. The goal is to generate "rows" where each row can contain a max of 12 elements. For example:

Input data can be something like this: const groups = [[1,2,3,4],[1,2,3,4,5,6], [1,2,3,4,5,6,7,8,9,10,11,12], [1,2,3,4,5,6,7], [1,2,3],[1,2,3]]

groups[0].length   groups[1].length = 10 -> row0
groups[2].length = 12 -> row1
groups[3].length   groups[4].length = 10 -> row3
groups[5].length = 3 -> row4

Output for such array should be:

const rows = [[[1,2,3,4], [1,2,3,4,5,6]], [[1,2,3,4,5,6,7,8,9,10,11,12]], [[1,2,3,4,5,6,7], [1,2,3]], [[1,2,3]]]

I was thinking of a recursive function for this but couldn't figure out how to solve it.

CodePudding user response:

You can use Array#reduce() to do this. The code first checks if the current last element (last "row") has more than 12 numbers in it if you add the next group:

(acc[acc.length - 1].flat().length   cv.length) <= 12

if it will be less than 12, the elements will get pushed into the "row":

acc[acc.length - 1].push(cv)

and if not, a new "row" will be added to the outer array:

acc.push([cv])

const groups = [[1, 2, 3, 4],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],[1, 2, 3, 4, 5, 6, 7],[1, 2, 3],[1, 2, 3]];

const rows = groups.reduce((acc, cv) => {
  (acc[acc.length - 1].flat().length   cv.length) <= 12 ?
      acc[acc.length - 1].push(cv) :
      acc.push([cv])
  return acc
}, [[]]);


console.log(JSON.stringify(rows))

CodePudding user response:

Here's one way to solve it recursively:

const regroup = (max, [g, ...gs], filled = [], curr = [], cc = 0) =>
  g == undefined
    ? filled .concat ([curr])
  : g .length   cc <= max
    ? regroup (max, gs, filled, curr .concat ([g]), cc   g.length)
  : regroup (max, gs, filled .concat ([curr]), [g], g .length)

const groups = [[1, 2, 3, 4], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 
                [1, 2, 3, 4, 5, 6, 7], [1, 2, 3], [1, 2, 3]]

console .log (regroup (12, groups))
.as-console-wrapper {max-height: 100% !important; top: 0}

We pass the maximum size and the list of items, and then we default three parameters:

  • filled will track the output rows we've filled; it starts with an empty array
  • curr stores the row we're working on; it also starts with an empty array
  • cc stores the count of all elements in the current row; it starts with zero

On each recursive call, we have one of three possibilities:

  • There are no more arrays to process, and we return all the filled rows with the current row appended.
  • The next array is small enough to fit in the current row, and we update the current to include it, and the current count to accommodate it.
  • The next array is too large, and we add the existing current row to the filled ones, and start a new current row with this array, setting the count appropriately.
  • Related