JavaScriptで指定した個数の要素による配列の重複順列をすべて生成する方法
はじめに
リテラル値の配列を第1引数として、数値を第2引数として受け取るJavaScript関数を作成する必要があります。この関数は、第2引数で指定された個数と同じ長さを持ち、入力配列の要素から作り得るすべての順列(重複あり)を格納した配列を返すものです。
要件の整理
例えば、入力配列と数値が以下のような場合を考えてみましょう。
const arr = ['k', 5]; const num = 3;
この場合、期待される出力は次のようになります。各要素は長さ3の配列で、「k」と「5」の組み合わせがすべて網羅されています。
const output = [ [ 'k', 'k', 'k' ], [ 'k', 'k', 5 ], [ 'k', 5, 'k' ], [ 'k', 5, 5 ], [ 5, 'k', 'k' ], [ 5, 'k', 5 ], [ 5, 5, 'k' ], [ 5, 5, 5 ] ];
なお、この種の組み合わせは数学的には重複順列(直積)と呼ばれます。生成される配列の総数は「入力配列の要素数 ÷ 指定個数のべき乗」で求まり、上記の例では 23 = 8 個となります。
実装コード
以下が実際のコードです。再帰処理を用いたシンプルで読みやすいアプローチを採用しています。
const arr = ['k', 5];
const num = 3;
const allPairs = (arr = [], num) => {
const res = [];
if(num === 0){
return [[]];
}
const subResult = allPairs(arr, num - 1);
for(let el of arr){
for(let sub of subResult){
res.push([el].concat(sub));
}
}
return res;
}
console.log(allPairs(arr, num));
コードの仕組み
この関数がどのように動作するのか、順を追って解説します。
- ベースケース: num が 0 になった時点で、空の配列を1つ含む
[[]]を返します。これにより再帰が終了し、空の配列を起点として組み合わせを積み上げていけるようになります。 - 再帰ステップ: まず
allPairs(arr, num - 1)を呼び出し、長さが num − 1 のすべての組み合わせを取得します。 - 組み合わせの構築: 入力配列の各要素
elを、サブ結果の各配列subの先頭に連結して新しい配列を作成し、結果配列に追加していきます。
この「1つ短い順列を先に求め、その先頭に各要素を付け足す」という発想により、任意の個数の順列を簡潔に生成できます。
出力結果
コンソールには以下のように出力されます。
[ [ 'k', 'k', 'k' ], [ 'k', 'k', 5 ], [ 'k', 5, 'k' ], [ 'k', 5, 5 ], [ 5, 'k', 'k' ], [ 5, 'k', 5 ], [ 5, 5, 'k' ], [ 5, 5, 5 ] ]
まとめ
再帰を活用することで、指定された個数分の要素を持つ重複ありの順列をすべて列挙することができます。コードも簡潔で拡張性が高い一方、結果の件数は入力サイズに対して指数関数的に増加するため、大きな配列や大きな個数を扱う際にはパフォーマンスへの影響に注意が必要です。
-
JavaScriptでオートコンプリート(入力補完)機能を実装する方法
JavaScriptによるオートコンプリートの実装検索フォームなどでユーザーの入力に合わせて候補を自動的に表示する「オートコンプリート(入力補完)」機能は、JavaScriptを使えばライブラリなしでも実装できます。本記事では、配列に格納されたデータを候補として表示し、マウスクリックやキーボード操作で選択できるオートコンプリートの作り方を、完全なサンプルコードとともに解説します。実装のポイントこのサンプルでは以下のような仕組みでオートコンプリートを実現しています。inputイベント:テキストフィールドに入力があるたびに発火し、入力値と前方一致する項目を候補リストとして動的に生成します。キーボー
-
JavaScriptで配列の要素を同じ配列内に複製する方法
JavaScriptでは、concat()メソッドとsort()メソッドを組み合わせることで、既存の配列の要素を同じ配列内に複製することができます。ここでは、実際に動作するサンプルコードを使って、その手順をわかりやすく解説します。 コード例 以下は、配列の要素を同じ配列内に複製するためのコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" cont