skip to Main Content

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) ?

5

Answers


  1. 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]));
    Login or Signup to reply.
  2. Here is the code that will give you the desired result:

    const groupSize = [1, 3, 5];
    const elements = ['a','b','c','d','e','f','g','h','i','j','k','l'];
    const maxGroupSize = Math.max(...groupSize);
    
    let groupIndex = 0;
    let startElementIndex = 0;
    let output = [];
    while (startElementIndex <= elements.length) {
      const currentGroupSize = groupSize[groupIndex] ?? maxGroupSize;
      output.push(elements.slice(startElementIndex, startElementIndex + currentGroupSize));
    
      startElementIndex += currentGroupSize;
      groupIndex++;
    }
    

    Steps:

    1. Determine the largest group maxGroupSize
    2. Iterate until there are elements left in the elements array
    3. On each iteration push the number of elements that corresponds to the current group size, otherwise use the value from maxGroupSize as a group size
    4. Update indexes for the start index(startElementIndex) and the group index(groupIndex)
    Login or Signup to reply.
  3. 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
    }
    
    Login or Signup to reply.
  4. Alright here is the best solution, you were right (almost), instead of using slice you should have used splice to get the right response, you can read about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

    The code below is exactly the same as yours but just with the correction. Hope this helps.

    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.splice(i, group_size[i]))
        }
    
    console.log(output);
    
    Login or Signup to reply.
  5. Use while loop and using max group size when groups out of bounds

    var group_size = [1, 3, 5];
    var elements = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",'m','n','o','p'];
    
    const max_size = Math.max(...group_size);
    const output = [];
    let last = 0;
    let i = 0;
    
    while (last < elements.length) {
      output.push(elements.slice(last, last += (group_size[i] ?? max_size)));
      i++;
    }
    console.log(output);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search