in_array() 在大陣列 (超過萬筆) 中查找時會線性掃描,效能急劇下降。本文介紹兩種 O(1) 或近 O(1) 的替代方案:鍵值翻轉 + isset() 以及 implode + strpos(),並解析適用場景與注意事項。
function inArrayFlip($needle, array $haystack): bool {
$flipped = array_flip($haystack);
return isset($flipped[$needle]);
}
array_flip() 將值變為鍵,建立雜湊表,查找複雜度 O(1)。isset() 比 array_key_exists() 快,且不觸發錯誤處理機制。$arr = ['a' => null, 'b' => 1];
isset($arr['a']); // false (值為 null)
array_key_exists('a', $arr); // true
若陣列可能包含 null 值且需視為「存在」,請改用 array_key_exists。
function inArrayStrpos($needle, array $haystack): bool {
$str = ',' . implode(',', $haystack) . ',';
$needle = ',' . $needle . ',';
return strpos($str, $needle) !== false;
}
,val1,val2,val3, 格式字串,首尾加逗號避免部分匹配 (如搜尋 1 不會誤匹 11)。strpos 底層用 Boyer-Moore/Horspool 演算法,極快。| 方法 | 耗時 (秒) | 相對速度 |
|---|---|---|
| in_array() | 2.45 | 1x (基準) |
| array_flip + isset() | 0.018 | ~136x |
| implode + strpos() | 0.032 | ~76x |
測試環境:PHP 8.1, Intel i7, 16GB RAM。實際倍數隨資料分佈波動,但量級差距明顯。
array_flip。array_key_exists 或預先過濾 null。PHP 8.1 引入 array_is_list() 可快速判斷是否為列表 (連續數值索引),若是列表可考慮 in_array 配合 true (嚴格模式) 仍有優化空間,但翻轉法仍為王道。
大陣列查找棄用 in_array,改用 array_flip + isset() 可獲得百倍以上加速。理解 isset 與 array_key_exists 對 null 的不同處理,能避免隱蔽 Bug。將翻轉雜湊表快取化,更能在高併發服務中穩定發揮極致效能。