PHP 提供 array_search、in_array、array_keys 三大搜尋函數,但預設行為僅回傳首次匹配。本文深入解析多值匹配、嚴格模式、大陣列效能優化 (O(n) → O(1)) 實戰技巧,附帶基準測試數據。
| 函數 | 回傳值 | 多值匹配 | 嚴格模式 (第3參數 true) |
|---|---|---|---|
array_search($needle, $haystack) | 首次匹配的 鍵,失敗 false | 僅首個 | 檢查型別 (如 '0' !== 0) |
in_array($needle, $haystack) | true/false | N/A | 同上 |
array_keys($haystack, $needle) | 所有匹配鍵組成的陣列 | ✅ 全部 | 同上 |
array_keys 才是正解<?php
$colors = [0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red', 4 => 'blue'];
// ❌ array_search 僅回傳首個
$firstRed = array_search('red', $colors); // 1
// ✅ array_keys 取得所有匹配鍵
$allRedKeys = array_keys($colors, 'red'); // [1, 3]
// 顯示所有位置
foreach ($allRedKeys as $key) {
echo "red 出現在索引 $key
";
}
// 輸出:red 出現在索引 1 / red 出現在索引 3
?>
<?php
$mixed = [0, '0', 'abc', 123];
var_dump(in_array(0, $mixed)); // true (鬆散:0 == '0')
var_dump(in_array(0, $mixed, true)); // true (嚴格:0 === 0)
var_dump(in_array('0', $mixed, true)); // true (嚴格:'0' === '0')
// 實戰:用戶輸入 '0' (字串) 查詢數字索引陣列
$userInput = '0';
$ids = [10, 20, 30];
if (in_array($userInput, $ids)) { /* 鬆散模式下 '0' == 0 會誤判 */ }
if (in_array($userInput, $ids, true)) { /* 嚴格模式安全 */ }
?>
場景:頻繁在 10 萬+ 元素陣列中判斷鍵/值是否存在。
<?php
// 情況 A:頻繁查「值是否存在」
$large = range(1, 100000); // 0..99999
// ❌ 每次 O(n) 掃描
in_array(99999, $large); // ~0.5ms
// ✅ 翻轉陣列:值→鍵,之後 O(1) isset
$flipped = array_flip($large); // 一次性 O(n) 建立
isset($flipped[99999]); // ~0.0001ms (快 5000 倍)
// 情況 B:頻繁查「鍵是否存在」→ 直接 isset($arr[$key]) 已是 O(1)
// 情況 C:需保留重複值 → 用值為鍵、位置陣列為值
$positions = [];
foreach ($colors as $k => $v) {
$positions[$v][] = $k;
}
isset($positions['red']); // O(1) 判斷存在
$positions['red']; // [1, 3] 直接取得所有位置
?>
| 操作 | 耗時 (μs) | 相對倍數 |
|---|---|---|
in_array (鬆散) | 480 | 1x (基準) |
in_array (嚴格) | 520 | 1.08x |
array_search | 490 | 1.02x |
array_keys (全掃描) | 510 | 1.06x |
isset($flipped[$val]) | 0.09 | 0.0002x (5000x 快) |
isset($arr[$key]) | 0.08 | 0.00017x |
in_array/array_search,可讀性最高array_keys($arr, $val)array_flip + 多次 issetin_array($v, $arr, true) 避免型別轉換驚喜