← PHP中的array_diff_key():只比较键名的数组差集 PHP中的array_diff_ukey():用自定义回调函数比较键名的数组差集(只比键) →

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

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

array_diff_assoc()用内置的比较规则判断键名是否相等(===)。但有时候你需要自定义比较逻辑——比如键名不区分大小写比较,或者用自定义的字符串比较规则。

array_diff_uassoc()就是干这个的:通过用户提供的回调函数来比较键名,返回第一个数组中有但其他数组中没有的条目(键名+值)。这个函数从PHP 5开始可用。

语法格式

array_diff_uassoc(array $array1, array $array2 [, array $... ], callable $key_compare_func): array

参数说明:

参数 说明 必填?
array1 作为基准的数组 必填
array2 用来对比的数组 必填
array3... 更多用来对比的数组 可选
key_compare_func 用户自定义的回调函数,用于比较键名 必填

返回值: 返回一个数组,包含所有在array1中但不在其他数组中的条目。

回调函数的要求

回调函数接收两个参数(两个要比较的键名),返回:

  • 负数:第一个键名小于第二个键名

  • 0:两个键名相等

  • 正数:第一个键名大于第二个键名

示例1:基础用法——自定义整数比较

<?php
function compare_keys($k1, $k2) {
    if ($k1 === $k2) {
        return 0;
    }
    return ($k1 > $k2) ? 1 : -1;
}

$config_default = [
    "host" => "localhost",
    "port" => 3306,
    "username" => "root",
    "timeout" => 30
];

$config_custom = [
    "HOST" => "db.example.com",  // 注意大小写
    "PORT" => 3307,
    "username" => "app_user",
    "charset" => "utf8"
];

$diff = array_diff_uassoc($config_default, $config_custom, "compare_keys");
print_r($diff);
?>

输出:

Array
(
    [host] => localhost
    [port] => 3306
    [timeout] => 30
)

因为默认比较(===)下,"host"和"HOST"不同,所以host、port、timeout都返回了。如果要用不区分大小写的比较,看下一个例子。

示例2:不区分大小写的键名比较

<?php
function case_insensitive_compare($k1, $k2) {
    // 转成小写后再比较
    $k1_lower = strtolower($k1);
    $k2_lower = strtolower($k2);
    
    if ($k1_lower === $k2_lower) {
        return 0;
    }
    return ($k1_lower > $k2_lower) ? 1 : -1;
}

$required_fields = ["USERNAME", "EMAIL", "PASSWORD"];
$submitted_data = [
    "username" => "代码号001",
    "email" => "user@test.com"
    // 没有password字段
];

$missing = array_diff_uassoc($required_fields, $submitted_data, "case_insensitive_compare");
print_r($missing);
?>

输出:

Array
(
    [PASSWORD] => 
)

array_diff_uassoc要求两个数组的结构相同才能正常工作。这个例子其实不太合适,更好的做法是用array_udiff_assoc。实际中更常见的是用array_diff_key结合array_change_key_case

个人建议: 如果需要不区分大小写比较键名,更简单的做法是用array_change_key_case()先把两个数组的键名统一转成小写,然后用普通的array_diff_assoc()。代码更清晰:

$normalized = array_change_key_case($submitted_data, CASE_LOWER);
$required_lower = array_change_key_case($required_fields, CASE_LOWER);

示例3:多个数组对比

<?php
function strict_compare($a, $b) {
    // 严格类型比较
    return $a <=> $b;  // PHP 7+ 的三元比较运算符
}

$team_leader = [
    "id" => 1001,
    "name" => "张伟",
    "role" => "leader",
    "department" => "技术部"
];

$team_member_a = [
    "id" => 1002,
    "name" => "李芳",
    "role" => "developer"
];

$team_member_b = [
    "id" => 1003,
    "name" => "王磊"
];

$unique_to_leader = array_diff_uassoc($team_leader, $team_member_a, $team_member_b, "strict_compare");
print_r($unique_to_leader);
?>

输出:

Array
(
    [department] => 技术部
)

只有"department"这个键名是leader独有的,id、name、role在其他数组中也都存在(不管值是什么)。

个人经验分享

  1. 什么时候需要array_diff_uassoc?

    • 键名需要自定义比较规则(不区分大小写、特殊字符串比较、版本号比较等)

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

    • 很少用,大多数场景用array_diff_assoc就够了

  2. 常见坑:返回值类型
    回调函数必须返回整数(负数、0、正数)。返回布尔值会出现奇怪的结果。

  3. 性能考虑
    自定义回调函数会有额外的函数调用开销。如果只需要不区分大小写,建议先统一转换键名再用array_diff_assoc,性能更好。

  4. PHP 7+ 的比较运算符
    PHP 7 引入了<=>(飞船运算符),可以简化回调函数:

    function compare($a, $b) {
        return $a <=> $b;
    }

    这个运算符自动返回-1、0、1。

  5. 实际应用场景
    我工作中用到array_diff_uassoc的场景很少。一个比较实用的例子是比较两个配置数组时,忽略某些键名的大小写差异。

示例4:代码号学习编程场景

<?php
// 场景:比较两个版本的API字段,键名包含版本号需要自定义比较
function version_key_compare($k1, $k2) {
    // 提取数字部分进行比较
    preg_match('/\d+/', $k1, $m1);
    preg_match('/\d+/', $k2, $m2);
    
    $v1 = isset($m1[0]) ? (int)$m1[0] : 0;
    $v2 = isset($m2[0]) ? (int)$m2[0] : 0;
    
    if ($v1 === $v2) {
        return 0;
    }
    return ($v1 > $v2) ? 1 : -1;
}

$api_v1 = [
    "user_v1" => ["name", "email"],
    "order_v1" => ["id", "amount"],
    "product_v1" => ["sku", "price"]
];

$api_v2 = [
    "user_v2" => ["name", "email", "phone"],
    "order_v2" => ["id", "amount", "status"]
];

$diff = array_diff_uassoc($api_v1, $api_v2, "version_key_compare");
echo "只在V1中存在的接口:\n";
print_r($diff);
?>

输出:

只在V1中存在的接口:
Array
(
    [product_v1] => Array
        (
            [0] => sku
            [1] => price
        )
)

示例5:最简单的回调写法

<?php
$arr1 = ["a" => 1, "b" => 2, "c" => 3];
$arr2 = ["A" => 1, "b" => 2];

// 不区分大小写比较
$result = array_diff_uassoc($arr1, $arr2, function($k1, $k2) {
    return strcasecmp($k1, $k2);  // PHP内置的不区分大小写字符串比较
});

print_r($result);
?>

输出:

Array
(
    [c] => 3
)

strcasecmp()本身已经返回符合要求的值(负数、0、正数),可以直接作为回调函数使用。

本节课程知识要点

  • array_diff_uassoc()自定义回调函数比较键名,返回第一个数组中独有的条目

  • array_diff_assoc()的区别:后者用内置的===比较键名

  • 回调函数必须返回整数(负数/0/正数)

  • 可以传入多个数组进行比较

  • 只比较键名,不比较值(值的比较是array_udiff_assoc()的事)

  • 从PHP 5开始可用

  • 大多数情况下array_diff_assoc()够用,需要自定义规则时才用这个

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