1

I'm trying to create a function that groups an array of numbers based on a length parameter. The length represents the max length of each sub-array. The code works as it is meant to for getting the sub arrays, but what I'd like to do is make it sort by odd and even.

function myFunctionA(myArr1, myVal) {
      newArr = [];
      for ( x = 0; x < myArr1.length; x += myVal) {
        newArr.push(myArr1.slice(x, x + myVal));
      }
      return newArr;
    }
Console.log(myfunction([1,2,3,4,5,6,7,8,9,10],3))

This returns [[1,2,3],[4,5,6],[7,8,9],[10]]

What I'd like to do is go through each sub array at a time until the sub arrays are the correct length and add any leftover values to a sub array/s

This would look like

[[1,3,5][2,4,6][7,9][8,10]]

Since arr 0 and arr 1 are the correct length that we have stated in the console.log statement, 7 8 9 and 10 are left over. But since the can't create a full sub array and they are odds and even, they form two sub arrays with a side of 2.

Other examples:

myfunction([1,2,3,4,5,6,7],2)
Should return [[1,3],[2,4],[5,7],[6]]

myfunction([1,2,3,4,5,6,7,8],1)
Should return [[1][2][3][4][5][6][7][8]]
de19
  • 75
  • 8
  • What if your input items are not sorted neither in ascending, nor in descending order? Would you need your output chunks be sorted or those may go in the order of appearance within original array? – Yevhen Horbunkov Jun 16 '20 at 12:17
  • I would suggest to write three functions instead: one to `partition` the array into evens and odds, one to `chunk` each of those into subarrays of a given length, and one to `zip`/flatten these back into a single result by alternating. – Bergi Jun 16 '20 at 12:42
  • What result do you expect for `myfunction([1,3,5,7,8,9,11,13,15],2)`? – Bergi Jun 16 '20 at 12:44

2 Answers2

1

You could take an array for collecting all odd and even values and then push the group if it has zero items. By having the wanted size, create a new array.

function chunkenator(array, size, fn) {
    let groups = [],
        result = [];

    for (let value of array) {
        const group = fn(value);
        if (!groups[group]) groups[group] = [];
        if (!groups[group].length) result.push(groups[group]);
        groups[group].push(value);
        if (groups[group].length === size) groups[group] = [];
    }

    return result;
}

console.log(chunkenator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, x => x % 2));
console.log(chunkenator([1, 3, 5, 7, 8, 9, 11, 13, 15], 3, x => x % 2));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    I'd suggest to make it more generic by passing a `grouper` function (here: `x => x%2`) as a callback – Bergi Jun 16 '20 at 12:43
0

One possibility would be to first seperate the numbers into even and odd numbers and then just loop over it, pushing the numbers into a new array switching between even and odd numbers.

It's not the cleanest piece of code, but it works.

function myfunction(arr, n) {
  const evenOdd = arr.reduce((acc, e) => {
    const ind = +(e % 2 === 0);
    acc[ind] = acc[ind] || [];
    acc[ind].push(e);
    return acc;
  }, []);

  let ind = 0, res = [[]];

  while (evenOdd[0].length || evenOdd[1].length) {
    for (let i = n; i--;) {
      const val = evenOdd[ind].shift();
      if (val) res[res.length - 1].push(val)
    }
    ind = (ind + 1) % 2
    res.push([])
  }

  res.pop()
  return res;
}

for (const n of [1, 2, 3]) {
  console.log(n,
    myfunction([1, 2, 3, 4, 5, 6, 7, 8], n)
  )
}
Moritz Roessler
  • 8,542
  • 26
  • 51