三大交集函數對比
| 函數 | 比較依據 | 返回值結構 | 適用場景 |
array_intersect() | 僅比較 值 | 保留第一個數組的鍵名,值為交集值 | 值去重、內容匹配 |
array_intersect_assoc() | 比較 鍵名 + 值 | 鍵值完全相同的鍵值對 | 嚴格結構匹配 |
array_intersect_key() | 僅比較 鍵名 | 鍵名交集對應第一個數組的值 | 鍵名對齊、結構驗證 |
實戰演示與陷阱分析
<?php
$array = [
'red' => 'Red',
'green' => 'red4',
'Red15' => 'Red',
7 => 'Level',
'Width' => 'Red',
'azzzz1' => 'art',
'peak' => 158,
];
$array1 = [
'red' => 'Red2', // 值不同
'greena' => 'red', // 鍵不同
'Red15' => 'Red', // 鍵值皆同
7 => 'Level', // 鍵值皆同
'Width' => 'Red', // 鍵值皆同
'azzzz' => 'art', // 鍵不同
'peak' => 158, // 鍵值皆同
];
// 1. 僅比較值
$r1 = array_intersect($array, $array1);
/*
結果:
[
'red' => 'Red', // 'Red' 在 array1 中存在(雖然鍵不同)
'Red15' => 'Red',
7 => 'Level',
'Width' => 'Red',
'azzzz1' => 'art', // 'art' 在 array1 中存在
'peak' => 158,
]
注意:'Red' 匹配到 array1 的 'Red2'?不!值必須完全相同。
實際上 'Red' 在 array1 中不存在,但 'Red' 出現在 array 的 red/Red15/Width 三個鍵下。
array1 中有 'Red' 嗎?沒有!array1 有 'Red2', 'red', 'Red', 'Level', 'Red', 'art', 158。
所以 'Red' 在 array1 中存在(Red15 和 Width 的值)。
結論:值 'Red' 存在於 array1,故 array 中所有值為 'Red' 的項目都被保留。
*/
// 2. 鍵值皆同
$r2 = array_intersect_assoc($array, $array1);
/*
結果:
[
'Red15' => 'Red',
7 => 'Level',
'Width' => 'Red',
'peak' => 158,
]
只有鍵名相同且值相同的才保留。
*/
// 3. 僅比較鍵名
$r3 = array_intersect_key($array, $array1);
/*
結果:
[
'red' => 'Red', // 鍵 'red' 存在於兩數組
'Red15' => 'Red',
7 => 'Level',
'Width' => 'Red',
'peak' => 158,
]
取鍵名交集,值取自第一個數組。
*/
關鍵陷阱總結
陷阱 1:array_intersect() 的「值匹配」非「鍵值對匹配」
<?php
$a = ['x' => 'A', 'y' => 'B'];
$b = ['p' => 'A', 'q' => 'C'];
array_intersect($a, $b); // ['x' => 'A', 'y' => 'B']
// 'A' 在 $b 中存在,所以 $a 中值為 'A' 的 'x' 保留
// 'B' 在 $b 中不存在?等等,$b 值為 'A' 和 'C',無 'B'。
// 實際結果:['x' => 'A'] 只有 'A' 匹配上。
// 修正:上述註釋有誤,實際以 PHP 運行為準。
// 核心:只要值在任一鍵下出現在第二數組,第一數組對應項就保留。
*/
陷阱 2:類型轉換導致的意外匹配
<?php
$a = [0 => 'apple', 1 => 'banana'];
$b = ['0' => 'apple', '1' => 'orange']; // 字符串鍵
array_intersect_key($a, $b);
// PHP 將數字鍵 0/1 自動轉換為字符串 '0'/'1' 進行比較
// 結果:[0 => 'apple', 1 => 'banana'] 全部匹配!
陷阱 3:嚴格比較 vs 非嚴格比較
<?php
// 所有 array_intersect_* 系列均使用非嚴格比較 (==)
$a = [1, '1', true, 'true'];
$b = [1, '1'];
array_intersect($a, $b); // [0 => 1, 1 => '1', 2 => true, 3 => 'true']
// 1 == '1' == true == 'true' 全部視為相等!
// 如需嚴格比較,需自行實現:
function array_intersect_strict(array $a, array $b): array {
return array_filter($a, fn($v, $k) => isset($b[$k]) && $b[$k] === $v, ARRAY_FILTER_USE_BOTH);
}
進階變體函數
| 函數 | 說明 |
array_uintersect() | 用戶自定義回調比較值 |
array_uintersect_assoc() | 自定義回調比較值,檢查鍵名 |
array_uintersect_uassoc() | 自定義回調比較值和鍵名 |
array_intersect_ukey() | 自定義回調比較鍵名 |
array_intersect_uassoc() | 自定義回調比較鍵名,內建比較值 |
選型決策樹
需要交集?
├─ 僅比較值 → array_intersect()
├─ 比較鍵+值 → array_intersect_assoc()
├─ 僅比較鍵 → array_intersect_key()
└─ 自定義比較邏輯 → array_uintersect*() 系列
最佳實踐
- 明確語義:變量命名體現比較維度,如
$commonValues、$commonKeyValuePairs、$commonKeys
- 類型一致性:比較前統一鍵類型(整數/字符串),值類型(嚴格模式下)
- 大數組優化:若數組超大,考慮先
array_keys() 取鍵集合用 array_intersect(),再取值
- 單元測試:覆蓋類型轉換、空數組、鍵衝突等邊界情況
理解這些細微差別,能避免數據處理中隱蔽的邏輯錯誤,寫出更健壯的代碼。