array_intersect_assoc()用内置的比较规则(===)同时比较键名和值。但有时候你需要自定义比较逻辑——比如键名不区分大小写、或者用某种特殊规则判断两个键名是否相等。
array_intersect_uassoc()就是干这个的:通过用户提供的回调函数来比较键名(值还是用===比较),返回第一个数组中有且在其他所有数组中都存在的条目。这个函数从PHP 5.0开始可用。
语法格式
array array_intersect_uassoc(array $array1, array $array2 [, array $... ], callable $key_compare_func): array
参数说明:
| 参数 | 说明 | 必填? |
|---|---|---|
| array1 | 基准数组 | 必填 |
| array2 | 第一个对比数组 | 必填 |
| array3... | 更多对比数组 | 可选 |
| key_compare_func | 用户自定义的回调函数,用于比较键名 | 必填 |
返回值: 返回一个数组,包含所有在array1中存在并且在所有其他数组中也存在的条目(键名经过回调判断为相等,且值也相等)。
回调函数的要求
回调函数接收两个参数(两个要比较的键名),返回:
-
负数:第一个键名 < 第二个键名
-
0:两个键名被视为相等
-
正数:第一个键名 > 第二个键名
和array_intersect_assoc()的区别
| 函数 | 键名比较方式 | 值比较方式 |
|---|---|---|
| array_intersect_assoc() | 内置=== |
=== |
| array_intersect_uassoc() | 用户回调函数 | ===(固定) |
示例1:不区分大小写的键名比较
<?php
$config_v1 = [
"Host" => "localhost",
"Port" => 3306,
"User" => "root",
"Timeout" => 30
];
$config_v2 = [
"host" => "192.168.1.100",
"port" => 3307,
"PASSWORD" => "123456"
];
// 自定义不区分大小写的键名比较
$result = array_intersect_uassoc($config_v1, $config_v2, "strcasecmp");
print_r($result);
?>
输出:
Array
(
[Host] => localhost
[Port] => 3306
)
strcasecmp是PHP内置的不区分大小写字符串比较函数。Host和host被视为相等,Port和port被视为相等,所以这两个条目被保留。User和Timeout在$config_v2中没有对应键名,所以不返回。
示例2:多个数组比较
<?php
function key_compare($k1, $k2) {
// 先转小写再比较
return strcasecmp($k1, $k2);
}
$schema_a = [
"USER_ID" => "int",
"USER_NAME" => "string",
"EMAIL" => "string",
"STATUS" => "int"
];
$schema_b = [
"user_id" => "bigint",
"user_name" => "varchar",
"created_at" => "datetime"
];
$schema_c = [
"UserId" => "int",
"UserName" => "string",
"Email" => "string"
];
$common = array_intersect_uassoc($schema_a, $schema_b, $schema_c, "key_compare");
print_r($common);
?>
输出:
Array
(
[USER_ID] => int
[USER_NAME] => string
)
忽略大小写的情况下,USER_ID/user_id/UserId被视为相同,USER_NAME/user_name/UserName被视为相同。EMAIL和STATUS不在所有数组中都存在。
示例3:自定义复杂键名比较规则
<?php
function ignore_prefix_compare($k1, $k2) {
// 去掉前缀"cfg_"后再比较
$clean_k1 = str_replace("cfg_", "", $k1);
$clean_k2 = str_replace("cfg_", "", $k2);
return strcmp($clean_k1, $clean_k2);
}
$default_config = [
"cfg_host" => "localhost",
"cfg_port" => 3306,
"cfg_user" => "root",
"cfg_timeout" => 30
];
$user_config = [
"host" => "192.168.1.100",
"port" => 3307,
"database" => "my_db"
];
$common = array_intersect_uassoc($default_config, $user_config, "ignore_prefix_compare");
print_r($common);
?>
输出:
Array
(
[cfg_host] => localhost
[cfg_port] => 3306
)
cfg_host和host(去掉前缀后都是host)被视为匹配,cfg_port和port也是。cfg_user在用户配置中没有对应,cfg_timeout也没有。
个人经验分享
-
什么时候用array_intersect_uassoc?
-
键名需要自定义相等规则(不区分大小写、忽略前缀/后缀、特殊字符处理)
-
内置的
===不够用的时候 -
和
array_diff_uassoc是对称操作(一个找交集,一个找差集)
-
-
内置函数作为回调
-
strcasecmp:不区分大小写比较字符串 -
strcmp:区分大小写比较字符串 -
如果你只需要不区分大小写,直接用
strcasecmp最省事
-
-
注意事项
-
这个函数只自定义键名的比较方式,值的比较仍然是严格的
=== -
如果需要同时自定义值和键名的比较规则,用
array_uintersect_assoc()
-
-
性能考虑
自定义回调会有额外开销。如果两个数组都很大,回调函数被调用的次数会很多。性能敏感的场景可以考虑预处理键名(比如统一转小写)然后用array_intersect_assoc()。
示例4:代码号学习编程场景
<?php
// 场景:多个学期成绩单的公共科目查找(科目名可能有大小写差异)
function subject_key_compare($k1, $k2) {
return strcasecmp(trim($k1), trim($k2)); // 忽略大小写和首尾空格
}
$semester1 = [
"Math" => 85,
"English" => 78,
"PHP" => 92,
"Database" => 88
];
$semester2 = [
"math" => 90, // 小写
"English " => 82, // 尾部有空格
"Python" => 85
];
$semester3 = [
" MATH " => 75, // 大小写混合+空格
"PHP" => 95,
"English" => 80
];
$common_subjects = array_intersect_uassoc($semester1, $semester2, $semester3, "subject_key_compare");
print_r($common_subjects);
?>
输出:
Array
(
[Math] => 85
[English] => 78
)
Math/math/MATH被视为相同科目,English/English/English也是。PHP只在第一和第三学期有,第二学期没有;Database只在第一学期有;Python只在第二学期有。
示例5:PHP 7+ 简洁回调写法
<?php
$arr1 = ["KEY_ONE" => 1, "KEY_TWO" => 2, "KEY_THREE" => 3];
$arr2 = ["key_one" => 100, "key_two" => 200, "key_four" => 400];
// 使用匿名函数
$result = array_intersect_uassoc($arr1, $arr2, function($a, $b) {
return strcasecmp($a, $b);
});
print_r($result);
?>
输出:
Array
(
[KEY_ONE] => 1
[KEY_TWO] => 2
)
PHP 5.3+支持匿名函数,不用单独定义命名函数,代码更紧凑。
示例6:回调函数需要返回整数
<?php
// 错误的回调:返回布尔值
function bad_compare($a, $b) {
return $a === $b; // 返回true/false,不是-1/0/1
}
// 正确的回调
function good_compare($a, $b) {
if ($a === $b) return 0;
return ($a > $b) ? 1 : -1;
}
// 更简洁的写法(PHP 7+)
function php7_compare($a, $b) {
return $a <=> $b;
}
$arr1 = ["a" => 1, "b" => 2];
$arr2 = ["A" => 1, "b" => 2];
// 错误的用得到意想不到的结果
// $wrong = array_intersect_uassoc($arr1, $arr2, "bad_compare");
$correct = array_intersect_uassoc($arr1, $arr2, "php7_compare");
print_r($correct);
?>
输出:
Array
(
[b] => 2
)
回调函数返回true(被转为1)会导致所有比较结果都是"大于",影响匹配逻辑。务必返回-1、0、1。
本节课程知识要点
-
array_intersect_uassoc()用用户自定义回调函数比较键名,同时比较值(===),返回交集 -
和
array_intersect_assoc()的区别:后者用内置===比较键名 -
回调函数必须返回整数(负数/0/正数)
-
只自定义键名的比较,值的比较始终是严格相等
-
常用内置函数
strcasecmp作为回调实现不区分大小写 -
可以传入多个数组进行比较
-
从PHP 5.0开始可用