JavaScriptで配列からランダムに要素を選択する方法|重複なしでn個取り出す
はじめに:やりたいこと
JavaScriptでは、配列の中から重複しないようにランダムな要素を複数個選び出したい場面があります。くじ引き、シャッフル機能、クイズのランダム出題など、さまざまな用途で活用できるテクニックです。
ここでは、次のような重複を含まない数値の配列を例に考えてみます。
const arr = [2, 5, 4, 45, 32, 46, 78, 87, 98, 56, 23, 12];
求められる要件は以下のとおりです。
- 一意なリテラルを含む配列と、取得する個数 n を受け取る関数を作成する
- 入力配列からランダムに n 個の要素を選び、配列として返す
- 出力配列内に同じ要素が2回以上現れないこと
実装コード
Math.random() でランダムなインデックスを生成し、すでに選んだ要素と重複しない場合だけ結果に追加する、シンプルで直感的なアプローチです。
const arr = [2, 5, 4, 45, 32, 46, 78, 87, 98, 56, 23, 12];
const chooseRandom = (arr, num = 1) => {
const res = [];
for(let i = 0; i < num; ){
const random = Math.floor(Math.random() * arr.length);
if(res.indexOf(arr[random]) !== -1){
continue;
};
res.push(arr[random]);
i++;
};
return res;
};
console.log(chooseRandom(arr, 4));実行結果
コンソールには、次のように4つの要素が出力されます。乱数を使用しているため、実行するたびに結果は変わります。
[ 5, 2, 4, 78 ]
コードのポイント
- Math.floor(Math.random() * arr.length):0 ~(配列の長さ − 1)の範囲の整数インデックスをランダムに生成します。
- indexOf による重複チェック:すでに選ばれている要素であれば continue でスキップし、カウンタ i を増やさずに再抽選します。
- デフォルト引数 num = 1:第2引数を省略した場合は、要素を1つだけ返します。
注意点:大量取得時のパフォーマンス
この方法は理解しやすい反面、要求する個数が元の配列の長さに近いほど重複抽選が頻発し、処理が遅くなるという弱点があります。
そのようなケースでは、Fisher-Yates(フィッシャー–イェーツ)シャッフルで配列全体を並べ替え、先頭の n 件を切り出す方法が効率的です。
const shufflePick = (arr, num = 1) => {
const copy = [...arr];
for(let i = copy.length - 1; i > 0; i--){
const j = Math.floor(Math.random() * (i + 1));
[copy[i], copy[j]] = [copy[j], copy[i]];
}
return copy.slice(0, num);
};
console.log(shufflePick(arr, 4)); // 例: [ 46, 12, 87, 5 ]こちらは必ず指定回数以内で処理が完了するため、配列サイズに対して安定したパフォーマンスを得られます。
まとめ
- 重複チェック方式(chooseRandom)は実装がシンプルで、少量の取得に適しています
- Fisher-Yates シャッフル方式は大量取得や全件シャッフルに最適です
- どちらも Math.random() ベースのため、セキュリティ目的の乱数が必要な場合は crypto.getRandomValues() の利用を検討しましょう
-
複数の値でJavaScript配列の要素を検索する方法
JavaScriptである配列(arr)が、別の配列(arr1)の複数の値・すべての要素を含んでいるかどうかを確認したい場面はよくあります。そんなときは、every()メソッドとincludes()メソッドを組み合わせることで、シンプルに判定できます。以下はそのサンプルコードです。 コード例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content=
-
JavaScriptの配列を文字列に変換する方法【toString()の使い方を解説】
JavaScriptで配列の要素をひとつの文字列として扱いたい場面はよくあります。そんなときに便利なのがtoString()メソッドです。このメソッドを使うと、配列の各要素がカンマ(,)で区切られたひとつの文字列に変換されます。以下は、ボタンをクリックすると配列の中身が文字列として画面に表示されるシンプルなサンプルコードです。サンプルコード<!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport content=width=device-