Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to batch group of array elements in reference to another array of group size?

How to batch group of array elements in reference to another array of group size ? I tried below code.

Code:

var group_size = [1, 3, 5];
var elements = ['a','b','c','d','e','f','g','h','i','j','k','l'];
        
var output = [];
    for (var i=0; i < group_size.length; i++) {
    output.push(elements.slice(i, group_size[i]))
}
console.log(output);

Output:

[["a"], ["b", "c"], ["c", "d", "e"]]

But expected output:

[['a'], ['b','c','d'],['e','f','g','h','i'],['j','k','l']]

If there are moe elements, then those elements to be grouped by max group_size element.

Example :

Input = ['a','b','c']
Output = [['a'], ['b','c']]

Input = ['a','b','c','d','e']
Output = [['a'], ['b','c','d'], ['e']]

Input = ['a','b','c','d','e','f','g','h','i','j','k','l']
Output = [['a'], ['b','c','d'],['e','f','g','h','i'],['j','k','l']]

Input = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p']
Output = [['a'], ['b','c','d'],['e','f','g','h','i'],['j','k','l','m','n'], ['o','p']]

I tried above code but that's limiting. How can I do it in ecma5 (js) ?

like image 983
Learner Avatar asked Oct 28 '25 03:10

Learner


2 Answers

What do you need for the solution:

  1. Keep a track of the largest group length.
  2. Keep a track of the offset at which the next group should start.
  3. Slice groups while they are within the range of the source array.
  4. If the array is larger than the sum of all groups, continue slicing chunks equal to the length of the largest group.

function splitIntoGroups (array, groups) {
    let output = [];
    let maxLength = 1;
    for (var i=0, offset=0; i < groups.length && offset < array.length; i++) {
        output.push(array.slice(offset, offset + groups[i]));
        offset += groups[i];
        maxLength = Math.max(maxLength, groups[i]);
    }
    while (offset < array.length) {
        output.push(array.slice(offset, offset + maxLength));
        offset += maxLength;
    }
    return output;
}

let elements = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'];
let groups = [1, 3, 5, 5, 5, 1000];

// when sum of all groups exceeds the source array,
// they are truncated to match the array
console.log(splitIntoGroups(elements.slice(0, 3), groups));
console.log(splitIntoGroups(elements.slice(0, 5), groups));
console.log(splitIntoGroups(elements.slice(0, 12), groups));
console.log(splitIntoGroups(elements, groups));

// when sum of all groups doesn't exceed the source array,
// the largest group is repeated until the end of the array
console.log(splitIntoGroups(elements, [1, 3, 5]));
like image 101
blakkwater Avatar answered Oct 29 '25 19:10

blakkwater


This code worked with all your provided inputs and should be compatible with es5

function groupArray(arr, sizes) {
  if (sizes.length == 0) {
    throw new Error('Sizes array must not be empty')
  }

  var maxSize = Math.max.apply(null, sizes)

  var index = 0
  var output = []
  
  for (var size of sizes) {
    if (index >= arr.length) break

    output.push(arr.slice(index, index + size))
    index += size
  }

  for (var i = index; i < arr.length; i += maxSize) {
    output.push(arr.slice(i, i + maxSize))
  }

  return output
}
like image 34
Gustavo Shigueo Avatar answered Oct 29 '25 19:10

Gustavo Shigueo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!