配列を任意のグループに分ける #javaScript

概要

JavaScript で配列を任意のグループに分ける。

例えば 7 人を 3 グループに分けると 3人-2人-2人みたいに分けたい。

考え方

  • 「配列」と「分けたい数」を引数で受け取る
  • まず割り切れる分を分けてしまう
  • 余りを改めて配る

素数が 7 だと 7 / 3 = 2 余り 1 になる。

まず 2-2-2 に分けたあと、余った分を先頭に追加して 3-2-2 にする。

実装

const splitArray = (array, splitSize) => {
  // まず割り切れる分を分ける
  const itemCount = Math.floor(array.length / splitSize)
  const splited = []
  for (let i = 0; i < splitSize; i++) {
    if (i === 0) {
      splited.push(array.slice(i, itemCount ));
      continue
    }
    splited.push(array.slice(itemCount * i, (itemCount * (i + 1))));
  }

  //  余りを配り直す
  const fraction = array.length % splitSize
  if (fraction === 0) {
    return splited
  }
  for (let i = 0; i < fraction; i++) {
    (splited[i]).push(array[array.length - (fraction-i)])
  }

  return splited
}

テスト

たとえば jest で書くなら。

test('7人を3つのグループに分ける', () => {
  const array = [1, 2, 3, 4, 5, 6, 7]
  const splitSize = 3
  expect(splitArray(array, splitSize)).toMatchObject([
    [1, 2, 7],
    [3, 4],
    [5, 6]
  ])
})

問題点

このやり方だと余りをあとから配るので、先頭のグループが [1, 2, 7] になってしまう。

これを [1, 2, 3] にするとしたら、どうするか。

  • 一度要素を総なめして、グループ分けをマークする
  • マークに沿って要素を詰め直す

こっちの方がよさそうな気がした。

もっとスマートなやり方もある気がする。