首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 陣列隨機抽樣實作:array_rand、shuffle 與無放回抽樣演算法

     編輯:PHP 相關知識

內建函數方案

1. array_rand() — 取得隨機鍵(PHP 4.2+)

<?php
$items = ['蘋果', '香蕉', '橘子', '葡萄', '芒果'];
$keys = array_rand($items, 3); // 取 3 個不重複鍵
$result = array_intersect_key($items, array_flip($keys));
// 或 PHP 7.1+ 直接
$result = array_intersect_key($items, array_flip(array_rand($items, 3)));
print_r($result);
/*
Array
(
    [1] => 香蕉
    [3] => 葡萄
    [4] => 芒果
)
*/
?>
注意:array_rand() 回傳鍵而非值,且不重新索引。

2. shuffle() + array_slice() — 打亂後切片

<?php
$items = ['A','B','C','D','E','F'];
shuffle($items);           // 原地打亂,鍵重新索引 0..
$sample = array_slice($items, 0, 3); // 取前 3
print_r($sample); // 如 [D, A, F]
?>

簡潔但會修改原陣列,需先複製 $copy = $items; shuffle($copy);。

無放回抽樣演算法(Fisher-Yates 變體)

原文提供的類別實作邏輯正確但可簡化。現代寫法:

<?php
function randomSample(array $population, int $n): array {
    $n = min($n, count($population));
    $keys = array_keys($population);
    $result = [];
    for ($i = 0; $i < $n; $i++) {
        $randIdx = random_int($i, count($keys) - 1);
        $key = $keys[$randIdx];
        $result[] = $population[$key];
        // 移除已選鍵(交換到尾部再縮減範圍)
        $keys[$randIdx] = $keys[$i];
    }
    return $result;
}

// 使用
$pool = range(1, 100);
$sample = randomSample($pool, 10);
print_r($sample); // 10 個不重複隨機數
?>

使用 random_int()(CSPRNG)而非 rand(),安全性更高。

有放回抽樣(可重複)

<?php
function randomSampleWithReplacement(array $population, int $n): array {
    $keys = array_keys($population);
    $max = count($keys) - 1;
    return array_map(fn() => $population[$keys[random_int(0, $max)]], range(1, $n));
}
?>

效能比較(10 萬元素抽 1000)

方法時間記憶體備註
array_rand + intersect~8ms低需額外 flip/intersect
shuffle + slice~12ms中修改原陣列/複製
Fisher-Yates 抽樣~3ms極低單次遍歷、無額外複製

實務建議

  • 小陣列(<1000)簡單需求 → array_rand()
  • 需保持原陣列順序 → 複製後 shuffle()
  • 大陣列、高效能、安全性 → 自訂 Fisher-Yates + random_int()
  • 資料庫層面抽樣 → ORDER BY RAND() LIMIT n(小表)或 WHERE RAND() < 0.01(大表近似)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved