← PHP中的array_intersect_key():用键名计算数组交集 PHP中的array_intersect_ukey():用自定义回调函数比较键名的数组交集(只比较键) →

PHP中的array_intersect_uassoc():用自定义回调函数比较键名的数组交集

原创 2026-05-22 PHP 已有人查阅

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内置的不区分大小写字符串比较函数。Hosthost被视为相等,Portport被视为相等,所以这两个条目被保留。UserTimeout$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被视为相同。EMAILSTATUS不在所有数组中都存在。

示例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_hosthost(去掉前缀后都是host)被视为匹配,cfg_portport也是。cfg_user在用户配置中没有对应,cfg_timeout也没有。

个人经验分享

  1. 什么时候用array_intersect_uassoc?

    • 键名需要自定义相等规则(不区分大小写、忽略前缀/后缀、特殊字符处理)

    • 内置的===不够用的时候

    • array_diff_uassoc是对称操作(一个找交集,一个找差集)

  2. 内置函数作为回调

    • strcasecmp:不区分大小写比较字符串

    • strcmp:区分大小写比较字符串

    • 如果你只需要不区分大小写,直接用strcasecmp最省事

  3. 注意事项

    • 这个函数只自定义键名的比较方式,值的比较仍然是严格的===

    • 如果需要同时自定义值和键名的比较规则,用array_uintersect_assoc()

  4. 性能考虑
    自定义回调会有额外开销。如果两个数组都很大,回调函数被调用的次数会很多。性能敏感的场景可以考虑预处理键名(比如统一转小写)然后用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开始可用

← PHP中的array_intersect_key():用键名计算数组交集 PHP中的array_intersect_ukey():用自定义回调函数比较键名的数组交集(只比较键) →
分享笔记 (共有 篇笔记)
验证码:
微信公众号