概要
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]
にするとしたら、どうするか。
- 一度要素を総なめして、グループ分けをマークする
- マークに沿って要素を詰め直す
こっちの方がよさそうな気がした。
もっとスマートなやり方もある気がする。