Split array into equal chunks, exclude the last chunk that is smaller and redistribute its items equally between the previous chunks

Viewed 25

I have an array of items :

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
// or more items

I have managed to split it into chunks by 3 items per array and pushed them into an array of arrays :

[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
  [10, 11] // <== the last one has less items than the others
]

I want to redistribute the items of the last array equally between the previous chunks :

// expected output
[
  [1, 2, 3, 10],
  [4, 5, 6, 11],
  [7, 8, 9],
]

or even more complex like redistrbuting the items at random positions :

// expected output
[
  [1, 2, 3, 10],
  [4, 5, 6],
  [7, 8, 9, 11],
]

so far this is what i have reached :

  let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  let arrayOfChunks = [];
  let amount = 3;
  for (let i = 0; i < array.length; i += amount) {
    const chunk = array.slice(i, i + amount);
    if (chunk.length === amount) {
      arrayOfChunks.push(chunk);
    } else {
      console.log(chunk);
      // output [10,11]
    }
  }
  return arrayOfChunks;

I tried making another loop dpending on the arrayOfChunks.length = 3 where I could redistribute the items of the last array evenly into the arrayOfChunks, but sometimes the arrayOfChunks.length = 5 which require another splitting and merging into the previous generated equal chunks.

thanks for your help :)

1 Answers

After chunking the array normally, pop off the last subarray if the chunk number didn't divide the original array length evenly. Then, until that last popped subarray is empty, push items to the other subarrays, rotating indicies as you go.

const evenChunk = (arr, chunkSize) => {
  const chunked = [];
  for (let i = 0; i < arr.length; i += chunkSize) {
    chunked.push(arr.slice(i, i + chunkSize));
  }
  if (arr.length % chunkSize !== 0) {
    const last = chunked.pop();
    let i = 0;
    while (last.length) {
      chunked[i].push(last.shift());
      i = (i + 1) % chunked.length;
    }
  }
  console.log(chunked);
};
evenChunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 7);
evenChunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3);

Related