統計陣列中出現頻率最高的前 N 個值,是日誌分析、推薦系統、熱門標籤等場景核心需求。本文展示標準實作、結果解讀與百萬級優化方案。
<?php
// 1. 生成測試資料:1000 個 1-1000 隨機數
$data = [];
for ($i = 0; $i < 1000; $i++) {
$data[] = random_int(1, 1000);
}
// 2. 統計頻率:值 => 次數
$freq = array_count_values($data); // O(n)
// 3. 依次數降序排序 (保持鍵值關聯)
arsort($freq); // O(k log k), k = 不同值數量
// 4. 取前 10
$top10 = array_slice($freq, 0, 10, true); // true 保留鍵值
// 5. 輸出格式化
foreach ($top10 as $value => $count) {
printf("數值:%d 出現次數:%d\n", $value, $count);
}
/*
輸出範例:
數值:255 出現次數:6
數值:443 出現次數:5
數值:906 出現次數:5
...
*/
?>
| 函數 | 作用 | 複雜度 | 注意 |
|---|---|---|---|
| array_count_values | 統計值出現次數,回傳 [值=>次數] | O(n) | 僅支援 string/int 值 |
| arsort | 值降序排序,保持鍵值關聯 | O(k log k) | k = unique 個數 |
| array_slice | 切片,第 4 參數 true 保留鍵 | O(m) | m = 取樣數 |
<?php
function getTopFreqValues(array $data, int $n = 10): array {
$freq = array_count_values($data);
arsort($freq);
$result = [];
$count = 0;
$lastFreq = -1;
foreach ($freq as $value => $freqCount) {
if ($count < $n) {
$result[$value] = $freqCount;
$count++;
$lastFreq = $freqCount;
} elseif ($freqCount === $lastFreq) {
// 第 N+1 個與第 N 個頻率相同,一併納入 (並列)
$result[$value] = $freqCount;
} else {
break;
}
}
return $result;
}
?>
SELECT value, COUNT(*) AS freq
FROM events
WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY value
ORDER BY freq DESC
LIMIT 10;
利用索引、分區表、物化視圖,效能碾壓 PHP 記憶體計算。
function topKFreq(Iterator $data, int $k): array {
$freq = []; // 記憶體可能爆炸,需分塊
// 實際生產用 HyperLogLog、Count-Min Sketch 近似算法
// 或 MapReduce / Flink / ClickHouse 等 OLAP 引擎
}
SplFixedArray 替代陣列存儲整數鍵值。<?php
// 假設從日誌讀取關鍵字
$keywords = ['php', 'laravel', 'php', 'mysql', 'redis', 'php', 'docker', 'laravel', 'k8s', 'php'];
$freq = array_count_values($keywords);
arsort($freq);
$top5 = array_slice($freq, 0, 5, true);
echo "熱門關鍵字 Top 5:\n";
foreach ($top5 as $kw => $cnt) {
echo "{$kw}: {$cnt}\n";
}
/*
php: 4
laravel: 2
mysql: 1
redis: 1
docker: 1
*/
?>
array_count_values 遇到陣列/物件會報 Warning 並跳過,確保陣列純量值。strtolower()。ini_set('memory_limit', '512M') 視資料量調整。頻率統計是數據分析基石,PHP 內建函數組合拳足夠應付中小規模;大規模務必下推至資料庫或流計算引擎,避免單機記憶體瓶頸。