この記事の例では、JavaScript を使用して配列内の値のインデックスをランダム化し、ランダムな配列を作成する方法を説明します。皆さんの参考に共有してください。詳細は以下の通りです。
今日、QW コミュニケーション グループで、配列のランダム化の問題について議論している学生を見かけました。そのアルゴリズムは非常に優れており、以前に実装したあまり「美しくない」方法を思い出しました。考えてみてください。機能を実装するためだけにビジネス コードを書くのに忙しいとき、より良い実装方法があるかどうかについてあまり考えないことがあります。
この配列の問題 (配列内の値を並べ替えて新しい配列を返す) に関する限り、私の以前の実装方法は次のとおりでした:
function randArr(arr) { var ret = [], obj = {}, i = arr.length, l = i, n; while (--i >= 0) { n = Math.floor( Math.random() * l ); if (obj[n] === void 0) { ret[ret.length] = obj[n] = arr[n]; } else { i++; } } return ret; }
上記のコードは機能しますが、「元の配列の長さ」ループを実行することを目的としており、各ループは元の配列内のインデックスをランダムに選択し、そのインデックスが存在するかどうかを判断します。フェッチされていない場合は、インデックスの値を新しい配列に入れます。フェッチされている場合は、デクリメント キー i を 1 ずつ増やします (目的は、フェッチされていない別のインデックスがフェッチされるまでサイクルを繰り返すことです)。この方法のパフォーマンスはあなたの性格に依存します。このアイデアを見た学生はその理由を理解できると思います。
次に、グループ内の生徒のアルゴリズムを与えます:
function randArr(arr) { var ret = [], i = arr.length, n; arr = arr.slice(0); while (--i >= 0) { n = Math.floor( Math.random() * i); ret[ret.length] = arr.splice(n, 1)[0]; } return ret; }
これは非常に賢いアルゴリズムです。各ループの後、ランダムなインデックスが取得され、その値が配列から削除されます。その後もインデックスがランダムに取得された場合、そのインデックスはその値ではなくなります。乱数の範囲は配列の長さの減少に応じて減少するため、一度に一定回数ループすることで理想的な結果が得られます。
また、改良版も見ました。これは、配列の削除操作によって引き起こされるいくつかのパフォーマンスの問題を考慮し、JK のシャッフル アルゴリズムを使用しています。つまり、各削除操作を位置置換操作 (フェッチされたこの値) に変更しています。インデックスは、現在のデクリメントキー i) に対応する値と交換され、配列全体への影響が最小限になるように、次のコードを追加します。
function randArr(arr) { var ret = [], i = arr.length, n; arr = arr.slice(0); while (--i >= 0) { n = Math.floor( Math.random() * i); ret[ret.length] = arr[n]; arr[n] = arr[i]; } return ret; }
最後に、「最小値から最大値までの値を持つランダムな配列を作成する」方法を示します。アルゴリズムの原理は上記と同様です。
function makeRandArr(min, max) { var ret = [], obj = {}, n; for (; max >= min; max--) { n = Math.ceil( Math.random() * (max - min) ) + min; ret[ret.length] = obj[n] || n; obj[n] = obj[max] || max; } return ret; }
この記事が皆様の JavaScript プログラミング設計に役立つことを願っています。