概要
もう少しシンプルに考えてできそうだと思ったのでやってみた。
- n進数変換を基に組み合わせを作成。
- 元の配列を使って、数値を配列要素に変換する。
コード
JS
// 要素の長さと組み合わせ数を基に、n進数列を1文字ずつ配列変換したものを作成。
function getCombArr(len = 2, comb = 1) {
const num = Math.pow(len, comb),
makeArr = (v, i) => {
const n = i.toString(len),
padStr = '0'.repeat(comb - n.length);
return (padStr + n).split('');
};
return [...Array(num).keys()].map(makeArr);
};
console.log(getCombArr(3, 2)); // [['0','0'],['0','1'],['0','2'],['1','0'],['1','1'],['1','2'],['2','0'],['2','1'],['2','2']]
// 上記関数を利用しつつ、組み合わせを作成
function getComb(arr = [], comb = 1) {
const base = getCombArr(arr.length, comb),
convert = v => arr[v],
makeArr = comb => comb.map(convert);
return base.map(makeArr);
};
console.log(getComb(['a', 'b', 'c'], 2)); // [['a','a'],['a','b'],['a','c'],['b','a'],['b','b'],['b','c'],['c','a'],['c','b'],['c','c']]
解説
n進数列への変換
3つの要素を2つずつ組み合わせる場合、重複ありで考えると3の2乗で9通り。
const num = Math.pow(len, comb)
数値iをn進数変換する。要素数が3つなら3進数に変換する形となる。
ex. 10進数の3 → 3進数の10, 10進数の8 → 3進数の22
const n = i.toString(len)
最大桁数(組み合わせ数)と同じ桁になるまで0埋めをしつつ、文字列の配列化。
ex. 0
→ "00"
→ ["0", "0"]
padStr = '0'.repeat(comb - n.length);
return (padStr + n).split('');
組み合わせパターンと同じ要素数の配列を、n進数を基にした配列に変換する。
[...Array(num).keys()].map(makeArr);
元の配列を基に変換する
- 上記手順でn進数配列を作成。
- 元の配列
arr
が["a", "b", "c"]
で、n進数配列内の要素が["0", "1"]であった場合、
[arr[0], arr[1]]という形式で変換させ、配列
["a", "b"]`を得る。 - 上記結果を配列としてまとめる。
function getComb(arr, comb) {
const base = getCombArr(arr.length, comb),
convert = v => arr[v],
makeArr = comb => comb.map(convert);
return base.map(makeArr);
};
注意点
- Number.toStringは2~36までしか対応してないため、36個以上の要素数を持つ配列の組み合わせに対応していない。