← PHP中的array_intersect_uassoc():用自定义回调函数比较键名的数组交集 PHP中的array_key_exists():检查数组中是否存在某个键名 →

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

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

array_intersect_key()用内置规则比较键名(===)。array_intersect_uassoc()同时比较键和值,键名用回调。那如果只想比较键名,但键名比较规则要自定义呢?

array_intersect_ukey()就是干这个的——通过用户提供的回调函数来比较键名,返回第一个数组中有且在其他所有数组中也存在的键名对应的(值本身不参与比较,只是跟着键名一起返回)。这个函数从PHP 5.1开始可用。

语法格式

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

参数说明:

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

返回值: 返回一个数组,包含所有在array1中存在并且在所有其他数组中也存在的键名对应的条目(只比较键名,不比较值)。

三种键名相关交集函数的区别

函数 键名比较方式 值比较方式 用途
array_intersect_key() 内置=== 不比较值 默认规则找键名交集
array_intersect_uassoc() 用户回调 === 自定义键名规则 + 值也要相等
array_intersect_ukey() 用户回调 不比较值 只自定义键名规则找交集

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

<?php
$user_data_v1 = [
    "UserName" => "张伟",
    "Email" => "zhang@test.com",
    "Phone" => "13800000000",
    "Age" => 25
];

$user_data_v2 = [
    "username" => "wei.zhang",
    "email" => "zhang@test.com",
    "address" => "北京市朝阳区"
];

// 不区分大小写比较键名
$common = array_intersect_ukey($user_data_v1, $user_data_v2, "strcasecmp");
print_r($common);
?>

输出:

Array
(
    [UserName] => 张伟
    [Email] => zhang@test.com
)

注意:PhoneAge在v2中没有对应键名,address在v1中没有。UserNameusername被视为匹配,Emailemail也是。值不参与比较——虽然v1的Email值是"zhang@test.com",v2的email值也是"zhang@test.com",但这里其实没比较值,只是键名匹配上了。

示例2:多个数组比较

<?php
function key_compare($k1, $k2) {
    // 去掉首尾空格后再比较
    return strcmp(trim($k1), trim($k2));
}

$source_a = [
    " id " => 101,
    "name" => "产品A",
    " price " => 299
];

$source_b = [
    "id" => 102,
    "name" => "产品B",
    "stock" => 50
];

$source_c = [
    " ID " => 103,
    "name" => "产品C",
    "category" => "电子"
];

$common_keys = array_intersect_ukey($source_a, $source_b, $source_c, "key_compare");
print_r($common_keys);
?>

输出:

Array
(
    [ id ] => 101
    [name] => 产品A
)

经过trim()处理后," id ""id"" ID "被视为相等;"name"也匹配上了。" price "在b和c中没有对应。

示例3:自定义复杂键名匹配(忽略前缀)

<?php
function ignore_prefix_compare($k1, $k2) {
    // 去掉前缀"field_"后比较
    $clean1 = str_replace("field_", "", $k1);
    $clean2 = str_replace("field_", "", $k2);
    return strcmp($clean1, $clean2);
}

$db_schema = [
    "field_id" => "int",
    "field_name" => "varchar",
    "field_price" => "decimal",
    "field_stock" => "int"
];

$api_response = [
    "id" => 1001,
    "name" => "机械键盘",
    "price" => 299
];

$common_fields = array_intersect_ukey($db_schema, $api_response, "ignore_prefix_compare");
print_r($common_fields);
?>

输出:

Array
(
    [field_id] => int
    [field_name] => varchar
    [field_price] => decimal
)

field_id匹配idfield_name匹配namefield_price匹配pricefield_stock在API响应中没有。值只返回第一个数组的(int/varchar/decimal),不比较值本身。

个人经验分享

  1. 什么时候用array_intersect_ukey?

    • 键名需要自定义相等规则(不区分大小写、忽略前缀、模糊匹配)

    • 不关心值是否相等,只关心键名是否存在

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

  2. 和array_intersect_uassoc的重要区别

    // array_intersect_ukey:只比较键名
    $result = array_intersect_ukey($arr1, $arr2, 'strcasecmp');
    // 键名匹配就保留,不管值是否相等
    
    // array_intersect_uassoc:键名和值都要匹配
    $result = array_intersect_uassoc($arr1, $arr2, 'strcasecmp');
    // 键名匹配 && 值相等(===)才保留

    选哪个取决于你是否需要比较值。

  3. 性能方面
    只比较键名不比较值,比array_intersect_uassoc快一些。大数据量下差异更明显。

  4. 常见使用场景

    • 数据源结构对齐:找出多个数据源的公共字段

    • 表单字段白名单(配合值处理)

    • 版本兼容性检查:新数据是否包含旧数据的核心字段

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

<?php
// 场景:多个数据源的公共字段提取(字段名可能有大小写差异)
function field_compare($f1, $f2) {
    return strcasecmp($f1, $f2);  // 不区分大小写
}

$db_columns = [
    "student_id" => "学生ID",
    "student_name" => "学生姓名",
    "student_score" => "成绩",
    "student_class" => "班级"
];

$csv_headers = [
    "Student_ID" => "学号",
    "Student_Name" => "姓名",
    "Student_Age" => "年龄"
];

$api_fields = [
    "studentId" => "id",
    "studentName" => "name",
    "studentScore" => "score"
];

// 找出三个数据源都有的公共字段
$common = array_intersect_ukey($db_columns, $csv_headers, $api_fields, "field_compare");
echo "三个数据源都包含的字段:\n";
print_r($common);

// 找出只在数据库中有、其他数据源没有的字段
$db_only = array_diff_ukey($db_columns, $csv_headers, $api_fields, "field_compare");
echo "\n只在数据库中的字段:\n";
print_r($db_only);
?>

输出:

三个数据源都包含的字段:
Array
(
    [student_id] => 学生ID
    [student_name] => 学生姓名
)

只在数据库中的字段:
Array
(
    [student_score] => 成绩
    [student_class] => 班级
)

示例5:PHP 7+ 简洁回调写法

<?php
$arr1 = ["KEY_ONE" => "value1", "KEY_TWO" => "value2", "KEY_THREE" => "value3"];
$arr2 = ["key_one" => "val1", "key_two" => "val2", "key_four" => "val4"];

// 使用匿名函数 + 飞船运算符
$result = array_intersect_ukey($arr1, $arr2, function($a, $b) {
    return strcasecmp($a, $b);
});

print_r($result);
?>

输出:

Array
(
    [KEY_ONE] => value1
    [KEY_TWO] => value2
)

示例6:数字和字符串键名的

<?php
function strict_compare($a, $b) {
    // 这种比较下,整数1和字符串"1"被认为是不同的
    return $a <=> $b;
}

function relaxed_compare($a, $b) {
    // 先转字符串再比较,忽略类型差异
    return strcmp((string)$a, (string)$b);
}

$arr1 = [1 => "apple", "2" => "banana", 3 => "cherry"];
$arr2 = ["1" => "fruit1", 2 => "fruit2", 3 => "fruit3"];

// 严格比较:1和"1"不同,"2"和2不同
$strict = array_intersect_ukey($arr1, $arr2, "strict_compare");
// 宽松比较:类型转换后比较
$relaxed = array_intersect_ukey($arr1, $arr2, "relaxed_compare");

echo "严格比较结果:\n";
print_r($strict);
echo "\n宽松比较结果:\n";
print_r($relaxed);
?>

输出:

严格比较结果:
Array
(
    [3] => cherry
)

宽松比较结果:
Array
(
    [1] => apple
    [2] => banana
    [3] => cherry
)

本节课程知识要点

  • array_intersect_ukey()用户自定义回调函数比较键名,返回键名匹配的条目

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

  • array_intersect_uassoc()的区别:后者同时比较值(===

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

  • 只比较键名,不比较值(值原样返回)

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

  • 从PHP 5.1开始可用

← PHP中的array_intersect_uassoc():用自定义回调函数比较键名的数组交集 PHP中的array_key_exists():检查数组中是否存在某个键名 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号