この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 配列からランダムに値を取り出す方法
SEOタイトル: PHP 配列からランダム値取得完全ガイド

この記事の要点
  • 1 件取得: $arr[array_rand($arr)] または $arr[mt_rand(0, count($arr)-1)]
  • 複数件取得: array_rand($arr, 3) はキーの配列を返す (順序はそのまま)
  • シャッフル: shuffle($arr) は参照渡し (返り値は bool)
  • セキュア用途 (パスワード / トークン): random_int() / random_bytes()
  • 再現性 が欲しい場合は mt_srand(42) でシード固定

基本: 1 件ランダム取得

$fruits = ['apple', 'banana', 'cherry', 'date'];

// 方法 1: array_rand (キーを返す)
$key = array_rand($fruits);     // 例: 2
$item = $fruits[$key];           // 'cherry'

// 方法 2: mt_rand
$item = $fruits[mt_rand(0, count($fruits) - 1)];

// 方法 3: シャッフルして先頭
shuffle($fruits);
$item = $fruits[0];
// ※ 元配列を破壊するので注意。1 件だけなら array_rand が効率的

複数件ランダム取得

$fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];

// array_rand に第二引数で件数指定
$keys = array_rand($fruits, 3);   // [0, 2, 4] のようなキー配列
$picked = array_map(fn($k) => $fruits[$k], $keys);

// ★ 注意点
// 1. キーの順序は維持される (シャッフルされない)
// 2. 重複なし
// 3. 件数が配列より大きいと Warning + null

// 完全ランダム順 + 重複なし
shuffle($fruits);
$picked = array_slice($fruits, 0, 3);

// 重複ありの抽選
$picked = [];
for ($i = 0; $i < 3; $i++) {
    $picked[] = $fruits[array_rand($fruits)];
}

連想配列の場合

$prices = [
    'apple'  => 100,
    'banana' => 200,
    'cherry' => 300,
];

// キー (商品名) を取得
$key = array_rand($prices);     // 'banana'
$price = $prices[$key];

// 値からランダム選択
$values = array_values($prices);
$value = $values[array_rand($values)];

// キーと値の組
$key = array_rand($prices);
[$key, $value] = [$key, $prices[$key]];

シード設定 (再現性)

// シードを固定すると毎回同じ順序になる (テスト用に便利)
mt_srand(42);
echo mt_rand(1, 100);   // 例: 53 (常に同じ)
echo mt_rand(1, 100);   // 例: 17

// シャッフルも同様に固定
mt_srand(42);
$arr = [1, 2, 3, 4, 5];
shuffle($arr);
print_r($arr);   // 毎回同じ並び

// テスト後はシードをリセット (現在時刻ベース)
mt_srand();

重み付きランダム (Weighted Random)

// 出現確率を変えたい場合
$weighted = [
    'common'    => 70,    // 70%
    'rare'      => 25,    // 25%
    'legendary' => 5,     //  5%
];

function weightedRandom(array $weights): string {
    $total = array_sum($weights);
    $rand = mt_rand(1, $total);
    $cum = 0;
    foreach ($weights as $key => $w) {
        $cum += $w;
        if ($rand <= $cum) return $key;
    }
    return array_key_first($weights);
}

echo weightedRandom($weighted);   // 70% で 'common'

// 1000 回試行で分布確認
$result = [];
for ($i = 0; $i < 1000; $i++) {
    $r = weightedRandom($weighted);
    $result[$r] = ($result[$r] ?? 0) + 1;
}
print_r($result);   // [common => 約700, rare => 約250, legendary => 約50]

セキュア用途 (random_int / random_bytes)

// パスワードリセットトークンやセッション ID には mt_rand 禁止
// → 暗号学的に安全な random_int を使う (PHP 7+)

$secureKey = random_int(1, 1000);
$bytes = random_bytes(32);                    // 32 バイトのランダム
$token = bin2hex(random_bytes(32));           // 64 文字 hex
$base64 = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');

// パスワード生成
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$password = '';
for ($i = 0; $i < 16; $i++) {
    $password .= $chars[random_int(0, strlen($chars) - 1)];
}

// 配列からセキュアに 1 件取得
$item = $arr[random_int(0, count($arr) - 1)];

各関数の使い分け

関数速度暗号安全用途
rand()速いX非推奨 (古い)
mt_rand()速いXゲーム / 一般用途
random_int()やや遅Oトークン / セキュリティ
random_bytes()やや遅Oバイト列生成
openssl_random_pseudo_bytes()やや遅OOpenSSL 拡張必須

Laravel Collection の random()

$users = User::all();

// 1 件
$random = $users->random();

// 複数件
$picked = $users->random(3);   // Collection

// shuffle
$shuffled = $users->shuffle();

// クエリビルダで
$random = User::inRandomOrder()->first();    // ORDER BY RAND()
$randomMany = User::inRandomOrder()->limit(5)->get();

// ★ MySQL の ORDER BY RAND() は大きなテーブルで激重
// → 件数が多いなら範囲取得 + PHP 側でランダム選択を推奨
$ids = User::pluck('id');
$pickedIds = $ids->random(5);
$users = User::whereIn('id', $pickedIds)->get();

他言語との比較

// JavaScript
const arr = ['a', 'b', 'c'];
const item = arr[Math.floor(Math.random() * arr.length)];

// シャッフル (Fisher-Yates)
for (let i = arr.length - 1; i > 0; i--) {
  const j = Math.floor(Math.random() * (i + 1));
  [arr[i], arr[j]] = [arr[j], arr[i]];
}
# Python
import random
arr = ['a', 'b', 'c']

random.choice(arr)            # 1 件
random.sample(arr, 2)         # 重複なし複数
random.choices(arr, k=5)      # 重複あり複数
random.shuffle(arr)           # in-place

# 重み付き
random.choices(['a', 'b', 'c'], weights=[70, 25, 5], k=1)

# セキュア
import secrets
secrets.choice(arr)
secrets.token_hex(32)

FAQ

Q: array_rand($arr, 1)array_rand($arr) は同じ?
A: 違う。array_rand($arr) はスカラー (キー 1 個)、array_rand($arr, 1) は配列 (キー 1 個入り)。後者を使うとそのまま foreach で書ける。

Q: 抽選システムの正当性を確保したい
A: random_int() 使用 + 抽選ログを sealed (改ざん防止) で保存。さらに監査用にシード値を時刻ベースで記録するか、公開した hash をコミットメント方式で先に公開。

Q: 10 万件から 100 件ランダム取得したい
A: 全件取得は無駄。SELECT id FROM users で id だけ取り、PHP 側で array_rand($ids, 100)、その後 WHERE IN で本体取得が高速。