Jesse Onolemen
Jesse Onolemen

Reputation: 1325

JS Split array into X chunks, then Y chunks and so on

How exactly could I split an array into 6 chunks, then 3 chunks, then 6 chunks, then 3 chunks and so on?

So say I have this dataset:

const datasaet = [
  { text: 'hi1' },
  { text: 'hi2' },
  { text: 'hi3' },
  { text: 'hi4' },
  { text: 'hi5' },
  { text: 'hi6' },
  { text: 'hi7' },
  { text: 'hi8' },
  { text: 'hi9' },
  { text: 'hi10' },
  { text: 'hi11' },
  { text: 'hi12' },
  { text: 'hi13' },
  { text: 'hi14' },
  { text: 'hi15' },
  { text: 'hi16' },
]

and I need to split it into an array like this:

const expected = [
  [
    { text: 'hi1' },
    { text: 'hi2' },
    { text: 'hi3' },
    { text: 'hi4' },
    { text: 'hi5' },
    { text: 'hi6' },
  ],
  [
    { text: 'hi7' },
    { text: 'hi8' },
    { text: 'hi9' },
  ],
  [
    { text: 'hi10' },
    { text: 'hi11' },
    { text: 'hi12' },
    { text: 'hi13' },
    { text: 'hi14' },
    { text: 'hi15' },
    { text: 'hi16' },
  ]
]

Essentially what I'm doing is splitting the array into 6 chunks if it's event and 3 chunks if it's odd.

However I don't know exactly how to go about doing this. My current attempt looks like this, I can split it into 6 chunks perfectly but how do I go about doing the next 3, and then the next 6 and so on:

const grouped = datasaet.reduce(
  (initital: any[], current, index, items) => {
    const isFirstOfSix = index % 6 === 0
    if (isFirstOfSix) {
      const nextSix = items.slice(index, index + 6)
      initital.push(nextSix)
    }

    return initital
  },
  []
) 

Upvotes: 0

Views: 89

Answers (2)

Ori Drori
Ori Drori

Reputation: 191976

You can create a function that takes an array, and array of chunk sizes. The function iterates the array, cycles between the chunk sizes, and uses slice to take the current chunk size from the original array:

const chunks = (arr, chunkSize) => {
  const result = [];
  
  let current = -1;

  for (let i = 0; i < arr.length; i += chunkSize[current]) {
    current = (current + 1) % chunkSize.length;
    
    result.push(arr.slice(i, i + chunkSize[current]));
  }

  return result;
}

const dataset = [{"text":"hi1"},{"text":"hi2"},{"text":"hi3"},{"text":"hi4"},{"text":"hi5"},{"text":"hi6"},{"text":"hi7"},{"text":"hi8"},{"text":"hi9"},{"text":"hi10"},{"text":"hi11"},{"text":"hi12"},{"text":"hi13"},{"text":"hi14"},{"text":"hi15"},{"text":"hi16"}];

const result = chunks(dataset, [6, 3]);

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

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370789

You might consider creating a copy of the array (to avoid mutating the original), then splicing out items until it's empty, checking and toggling a boolean that indicates whether to remove 6 or 3 items on the current iteration:

const datasaet = [
  { text: 'hi1' },
  { text: 'hi2' },
  { text: 'hi3' },
  { text: 'hi4' },
  { text: 'hi5' },
  { text: 'hi6' },
  { text: 'hi7' },
  { text: 'hi8' },
  { text: 'hi9' },
  { text: 'hi10' },
  { text: 'hi11' },
  { text: 'hi12' },
  { text: 'hi13' },
  { text: 'hi14' },
  { text: 'hi15' },
  { text: 'hi16' },
]

const tempArr = datasaet.slice();
const output = [];
let removeSix = true;
while (tempArr.length) {
  output.push(tempArr.splice(0, removeSix ? 6 : 3));
  removeSix = !removeSix;
}
console.log(output);

Upvotes: 1

Related Questions