何をしたいユーティリティか:「ランダム要素取得」
ここでの「ランダム要素取得」は、配列の中から 1 要素(または複数要素)をランダムに取り出す処理です。
「配列シャッフル」が「順番を全部ランダムにする」のに対して、「ランダム要素取得」は「欲しい数だけランダムに抜き取る」イメージです。
業務だと、例えば次のような場面で使います。
画面に表示するおすすめ商品を、候補リストからランダムに 1 件選ぶ。
テストデータの中から、毎回違うサンプルを 1 件だけ使いたい。
ユーザーをランダムに 1 人ピックアップして、デモ用に使いたい。
こういう処理を毎回手書きするのではなく、「ランダム要素取得ユーティリティ」としてまとめておくと、コードがかなりスッキリします。
一番基本:配列からランダムに 1 要素を取り出す
単純な 1 要素取得の実装
まずは、「配列から 1 要素だけランダムに取り出す」関数です。
function sampleOne(array) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
const index = Math.floor(Math.random() * array.length);
return array[index];
}
JavaScript重要なポイントをかみ砕いて説明する
最初に「配列かどうか」と「空配列でないか」をチェックしています。
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
JavaScript空配列からは要素を取り出せないので、その場合は undefined を返すようにしています。
業務コードでは、「空のときどうするか」を決めておくことが大事です。
次に、ランダムなインデックスを計算しています。
const index = Math.floor(Math.random() * array.length);
JavaScriptMath.random() は 0 以上 1 未満のランダムな数を返します。
それに array.length を掛けると、0 以上 length 未満の実数になります。Math.floor で小数点以下を切り捨てることで、0 以上 length - 1 以下の整数がランダムに 1 つ得られます。
この範囲が「配列の有効なインデックスの範囲」と一致しているのがポイントです。
最後に、そのインデックスの要素を返します。
return array[index];
JavaScriptこれで、「配列の中から 1 要素をランダムに取り出す」処理が完成です。
実際の動き
const colors = ["red", "green", "blue", "yellow"];
sampleOne(colors); // 例: "green"
sampleOne(colors); // 例: "blue"
sampleOne(colors); // 例: "red"
JavaScript何度呼び出しても、毎回どれが返ってくるかは分かりませんが、
どの要素も「同じ確率」で選ばれます。
複数要素をランダムに取り出す(重複なし)
「ランダムに N 件だけ欲しい」ケース
業務では、「1 件だけ」ではなく「ランダムに 3 件欲しい」「ランダムに 10 件欲しい」といったケースもよくあります。
しかも、「同じ要素を 2 回選びたくない(重複なし)」ことが多いです。
この場合は、「シャッフル+先頭 N 件」が一番素直です。
function sampleMany(array, count) {
if (!Array.isArray(array) || array.length === 0 || count <= 0) {
return [];
}
const copy = array.slice();
for (let i = copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const tmp = copy[i];
copy[i] = copy[j];
copy[j] = tmp;
}
return copy.slice(0, Math.min(count, copy.length));
}
JavaScript重要なポイントを深掘りする
最初に、入力チェックをしています。
if (!Array.isArray(array) || array.length === 0 || count <= 0) {
return [];
}
JavaScript配列でない、空配列、count が 0 以下のときは、結果は空配列にしています。
「何も選べない状況では空配列」というルールにしておくと、呼び出し側の処理がシンプルになります。
次に、元の配列を壊さないようにコピーを作っています。
const copy = array.slice();
JavaScriptここから先は、「配列シャッフル」で説明した Fisher–Yates シャッフルと同じです。copy をインプレースでシャッフルし、最後に先頭 count 件を切り出します。
return copy.slice(0, Math.min(count, copy.length));
JavaScriptcount が配列の長さより大きい場合でも、Math.min で長さに丸めているので、
「存在しない数を要求してエラーになる」ことはありません。
実際の動き
const users = ["A", "B", "C", "D", "E"];
sampleMany(users, 2); // 例: ["C", "A"]
sampleMany(users, 3); // 例: ["E", "B", "D"]
sampleMany(users, 10); // 例: ["B", "E", "A", "D", "C"](最大でも 5 件)
JavaScript毎回違う組み合わせが返ってきますが、
「同じ要素が 2 回入る」ことはありません。
複数要素をランダムに取り出す(重複あり)
「重複してもいいから N 回ランダムに選びたい」ケース
ときどき、「同じ要素が何度選ばれてもよい」ケースもあります。
例えば、「ガチャを 10 回引く」ようなイメージです。
この場合は、単純に sampleOne を count 回呼び出すだけで実現できます。
function sampleManyWithReplacement(array, count) {
if (!Array.isArray(array) || array.length === 0 || count <= 0) {
return [];
}
const result = [];
for (let i = 0; i < count; i++) {
result.push(sampleOne(array));
}
return result;
}
JavaScript実際の動き
const prizes = ["A", "B", "C"];
sampleManyWithReplacement(prizes, 5);
// 例: ["B", "C", "B", "A", "B"] // 同じものが何度も出てよい
JavaScript「重複なし」と「重複あり」で関数を分けておくと、
呼び出し側の意図がコードにそのまま表れて読みやすくなります。
実務で意識してほしい設計のポイント
「空配列のときどうするか」を必ず決める
ランダム要素取得で一番ハマりやすいのは、「空配列から選ぼうとしてエラーになる」パターンです。
例えば、array.length が 0 のときに Math.random() * array.length をしても 0 になり、index は 0 になりますが、array[0] は undefined です。
ここを「仕様」としてどう扱うかを決めておくのが大事です。
1 要素取得なら「空配列なら undefined を返す」。
複数要素取得なら「空配列なら空配列を返す」。
といったルールをユーティリティ側で固定しておくと、
呼び出し側は「戻り値が undefined や空配列のときは“選べなかった”とみなす」と決めるだけで済みます。
「重複あり」と「重複なし」を明確に分ける
業務でのバグの典型パターンのひとつが、「重複してはいけないのに重複してしまう」ケースです。
ランダム要素取得でも同じで、
重複してはいけないのに sampleManyWithReplacement 的な動きをしてしまう。
重複してもいいのに、わざわざシャッフルしてから切り出している。
といったミスマッチが起きがちです。
関数名で意図をはっきりさせるのがおすすめです。
sampleMany → 重複なし。sampleManyWithReplacement → 重複あり。
こうしておくと、コードを読むだけで「どういう前提のランダムなのか」が分かります。
「ランダム性の質」がどれくらい重要かを考える
Math.random() は「暗号学的に強い乱数」ではありませんが、
多くの業務用途(表示順のランダム化、テストデータのランダム化など)では十分です。
ただし、「抽選」「くじ」「セキュリティに関わるトークン生成」など、
不正や予測可能性が問題になる場面では、Math.random() では不十分です。
ランダム要素取得ユーティリティは、基本的には「業務ロジック用の軽いランダム」として位置づけ、
「セキュリティ用途のランダム」は別の仕組み(暗号学的乱数)で扱う、と分けて考えるのが安全です。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを何度か実行してみてください。
const colors = ["red", "green", "blue", "yellow"];
sampleOne(colors);
sampleMany(colors, 2);
sampleMany(colors, 10);
sampleManyWithReplacement(colors, 5);
JavaScript「毎回違う結果になること」「重複なし版と重複あり版で結果の性質が違うこと」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function sampleOne(...) { ... }
export function sampleMany(...) { ... }
export function sampleManyWithReplacement(...) { ... }
JavaScriptのような関数を置き、
「配列からランダムに取りたくなったら、必ずこの“ランダム要素取得ユーティリティ”を通す」
というルールを作ってみてください。
それだけで、あなたの「ランダムな選択」は、場当たり的な書き方から、意図と一貫性を備えた業務レベルの実装に変わっていきます。

