業務中常需「找出數組裡重複出現的元素」。PHP 內置函數法簡潔,手寫雙循環法易於理解邏輯。本文對比兩種實現,附性能測試建議。
<?php
function fetchRepeatByBuiltin(array $array): array {
$unique = array_unique($array); // 去重,保留首次出現的鍵值
$repeat = array_diff_assoc($array, $unique); // 比較鍵與值,找出被去重掉的項
return $repeat; // 返回重複項(保留原鍵名)
}
// 測試
$arr = ['apple', 'iphone', 'miui', 'apple', 'orange', 'orange'];
print_r(fetchRepeatByBuiltin($arr));
/*
輸出:
Array
(
[3] => apple
[5] => orange
)
*/
?>
原理:array_unique 保留第一次出現的值,後續重複值被丟棄;array_diff_assoc 比較鍵名+鍵值,將原數組中「不在去重數組裡」的項(即重複項)找出。
優點:代碼極少、可讀性強、C 層實現速度快。缺點:會保留原鍵名,若需連續索引需額外 array_values。
<?php
function fetchRepeatByLoop(array $array): array {
$len = count($array);
$repeat = [];
for ($i = 0; $i < $len; $i++) {
for ($j = $i + 1; $j < $len; $j++) {
if ($array[$i] === $array[$j]) {
$repeat[] = $array[$i];
break; // 找到第一個重複即跳出內層,避免同一值重複入結果
}
}
}
return $repeat;
}
// 測試
$arr = ['apple', 'iphone', 'miui', 'apple', 'orange', 'orange'];
print_r(fetchRepeatByLoop($arr));
/*
輸出:
Array
(
[0] => apple
[1] => orange
)
*/
?>
優點:邏輯直觀、可控性強(如需統計重複次數、記錄位置易擴展)。缺點:O(n²) 複雜度,大數組(>1萬)明顯慢。
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| 常規業務、數組 < 1萬 | 方法一 (內置函數) | 代碼簡潔、C 底層優化、可讀性佳 |
| 超大數組 (10萬+) | 方法一 或 改用 array_count_values | 雙循環 O(n²) 會超時;array_count_values 統計頻率再篩選 O(n) |
| 需保留原鍵名/位置信息 | 方法二 或 內置函數 + 額外邏輯 | 內置函數丟失重複項的原始位置 |
| 教學/面試/特殊判斷邏輯 | 方法二 | 展示算法思維 |
<?php
$arr = ['apple', 'iphone', 'miui', 'apple', 'orange', 'orange'];
$counts = array_count_values($arr); // ['apple'=>2, 'iphone'=>1, 'miui'=>1, 'orange'=>2]
$repeat = array_filter($counts, fn($v) => $v > 1); // 只保留重複的
print_r($repeat); // ['apple'=>2, 'orange'=>2]
?>
array_count_values 返回「值 => 次數」,一次性解決「哪些重複、重複幾次」,性能 O(n),強烈推薦作為通用方案。