從大量數值陣列中快速找出不重複的最大/最小前 N 個,是統計分析常見需求。本文展示標準庫函數組合實現,並分析時間複雜度與大數據優化方案。
<?php
// 1. 生成測試資料:1 萬個 1-100000 隨機數
$data = [];
for ($i = 0; $i < 10000; $i++) {
$data[] = random_int(1, 100000);
}
// 2. 去重
$unique = array_unique($data); // O(n) 平均,保留首次出現的鍵值
// 3. 排序 (由小到大)
sort($unique); // O(k log k), k = unique count, 重設鍵值為 0..k-1
// 4. 取最小 Top 10
$minTop10 = array_slice($unique, 0, 10); // O(1) 切片
// 5. 取最大 Top 10 (需倒序或反向切片)
$maxTop10 = array_slice($unique, -10, 10); // 從尾部取 10 個
// 若需由大到小排列
$maxTop10 = array_reverse($maxTop10);
// 輸出
echo "Min Top 10:\n";
print_r($minTop10);
echo "Max Top 10:\n";
print_r($maxTop10);
?>
Min Top 10:
Array
(
[0] => 16
[1] => 19
[2] => 22
[3] => 31
[4] => 40
[5] => 49
[6] => 71
[7] => 74
[8] => 80
[9] => 92
)
Max Top 10:
Array
(
[0] => 99997
[1] => 99991
[2] => 99973
[3] => 99958
[4] => 99955
[5] => 99946
[6] => 99939
[7] => 99933
[8] => 99927
[9] => 99900
)
| 步驟 | 函數 | 複雜度 | 說明 |
|---|---|---|---|
| 去重 | array_unique | O(n) | 內部用雜湊表,平均線性 |
| 排序 | sort | O(k log k) | k = 去重後數量,快速排序變體 |
| 切片 | array_slice | O(m) | m = 取樣數 (10),極小 |
| 總計 | O(n + k log k) | n=10000 時極快 (< 0.01s) |
function getTopN(array $data, int $n, bool $largest = true): array {
$heap = $largest ? new SplMinHeap() : new SplMaxHeap(); // 反向堆
foreach ($data as $val) {
if ($heap->count() < $n) {
$heap->insert($val);
} elseif (($largest && $val > $heap->top()) || (!$largest && $val < $heap->top())) {
$heap->extract();
$heap->insert($val);
}
}
$result = [];
foreach ($heap as $v) $result[] = $v;
return $largest ? array_reverse($result) : $result; // 排序輸出
}
SELECT DISTINCT val FROM table ORDER BY val DESC LIMIT 10,利用索引與查詢優化器。array_unique 保留首次出現的鍵值,sort() 會重設數字鍵值,關聯鍵值會丟失。array_slice($arr, -10) 當陣列少於 10 個元素時,回傳整個陣列,不會報錯。array_unique([0.1+0.2, 0.3]) 可能不視為相等,需先 array_map(fn($v)=>round($v,10), $arr)。<?php
function arrayTopN(array $data, int $n = 10, bool $unique = true, bool $largest = true): array {
if ($unique) $data = array_unique($data);
if ($largest) {
rsort($data);
} else {
sort($data);
}
return array_slice($data, 0, $n);
}
// 使用
$min10 = arrayTopN($data, 10, true, false);
$max10 = arrayTopN($data, 10, true, true);
?>
標準庫組合拳簡潔高效,覆蓋 90% 場景;大數據改用堆或下推到資料庫,架構層面解決效能問題。