去除陣列重複值時,array_unique() 是最直觀的選擇,但實測發現 array_keys(array_flip($arr)) 或雙重 array_flip() 效能遠優於前者。本文從 C 原始碼層面剖析兩者實作差異,揭示效能落差根本原因。
$test = [];
for ($i = 0; $i < 10000; $i++) {
$test[] = rand(0, 100); // 大量重複值
}
// array_unique
$start = microtime(true);
$out = array_unique($test);
echo 'array_unique: ' . (microtime(true) - $start) . "s\n"; // ~0.069s
// array_flip + array_keys
$start = microtime(true);
$out = array_keys(array_flip($test));
echo 'flip + keys: ' . (microtime(true) - $start) . "s\n"; // ~0.0015s
// 雙重 array_flip
$start = microtime(true);
$out = array_flip(array_flip($test));
echo 'flip + flip: ' . (microtime(true) - $start) . "s\n"; // ~0.0014s
結論:array_flip 方案比 array_unique 快約 45 倍。
zend_hash_next_index_insert()zend_hash_index_update() / zend_symtable_update()Bucket 指標陣列 arTmpzend_qsort() 進行 快速排序(塊樹排序變體)Bucket 索引陣列php_array_data_compare 需處理型別轉換、字串比較等zend_hash_del 移除重複項| 場景 | 推薦寫法 | 備註 |
|---|---|---|
| 純量值陣列去重(int/string) | array_keys(array_flip($arr)) | 最快,保留最後出現的鍵名 |
| 需保留第一次出現的鍵名 | array_flip(array_flip($arr)) | 雙重 flip 會反轉兩次,保留首次鍵名 |
| 物件陣列或需自訂比較邏輯 | array_unique($arr, SORT_REGULAR) | 唯一支援物件比較的內建函數 |
| 關聯陣列需保留鍵名關係 | 同上 | flip 會丟失原鍵名 |
PHP 7.3 起 array_unique() 針對整數陣列優化了排序演算法,但哈希表方案在大多數情況下仍具優勢。建議:
array_keys(array_flip())array_unique()理解底層實作差異,能在效能敏感路徑做出正確選擇,避免不必要的 CPU 浪費。