有时候你只关心数组里出现了哪些键名,不关心对应的值是什么。比如两个配置文件,想找出第一个配置文件里有哪些配置项是第二个里没有的。
array_diff_key()就是干这个的——比较两个或多个数组的键名,返回在第一个数组中存在、但在其他数组中不存在的那些条目(键名+值一起返回)。这个函数从PHP 5.1开始可用。
语法格式
array_diff_key(array $array1, array $array2 [, array $... ]): array
参数说明:
| 参数 | 说明 | 必填? |
|---|---|---|
| array1 | 作为基准的数组 | 必填 |
| array2 | 用来对比的数组 | 必填 |
| array3... | 更多用来对比的数组 | 可选 |
返回值: 返回一个数组,包含所有在array1中但不在其他数组中的键名及其对应的值。
和array_diff()、array_diff_assoc()的区别
| 函数 | 比较内容 | 返回条件 |
|---|---|---|
| array_diff() | 只比较值 | 值不在其他数组中 |
| array_diff_key() | 只比较键名 | 键名不在其他数组中 |
| array_diff_assoc() | 键名+值都看 | 键名或值有任何一个不同 |
示例1:基础用法
<?php
$user_permissions_a = [
"view" => true,
"edit" => true,
"delete" => false,
"export" => true
];
$user_permissions_b = [
"view" => true,
"edit" => true,
"share" => false
];
$diff_keys = array_diff_key($user_permissions_a, $user_permissions_b);
print_r($diff_keys);
?>
输出:
Array
(
[delete] => false
[export] => true
)
键名"delete"和"export"在第二个数组中不存在,所以返回这两个条目。值是什么不重要,只看键名。
示例2:多个数组比较
<?php
$config_default = [
"host" => "localhost",
"port" => 3306,
"username" => "root",
"password" => "",
"charset" => "utf8"
];
$config_local = [
"host" => "192.168.1.100",
"port" => 3307,
"username" => "admin"
];
$config_override = [
"host" => "db.example.com",
"username" => "app_user"
];
// 找出只在默认配置中存在的键名
$only_in_default = array_diff_key($config_default, $config_local, $config_override);
print_r($only_in_default);
?>
输出:
Array
(
[password] =>
[charset] => utf8
)
host、port、username在其他配置中都出现了(不管值是什么),所以被排除。password和charset是默认配置独有的键名。
示例3:索引数组的键名比较
<?php
$weekdays_full = ["周一", "周二", "周三", "周四", "周五"];
$weekdays_short = ["周一", "周三", "周五"];
$diff = array_diff_key($weekdays_full, $weekdays_short);
print_r($diff);
?>
输出:
Array
(
[1] => 周二
[3] => 周四
)
索引数组的键名就是数字下标。weekdaysfull的下标1(周二)和下标3(周四)在weekdaysfull的下标1(周二)和下标3(周四)在weekdays_short中不存在,所以返回。
个人经验分享
-
什么时候用array_diff_key而不是array_diff?
-
比较两个关联数组的结构差异,不关心值具体是什么
-
检查API返回的字段是否完整
-
找出哪些配置项是额外添加的
-
数据库表结构对比(字段名列表)
-
-
实际场景:检查数据完整性
$required_fields = ["id", "name", "email", "phone", "address"]; $submitted_data = ["id" => 1, "name" => "张伟", "email" => "test@test.com"]; $missing_fields = array_diff_key(array_flip($required_fields), $submitted_data); // array_flip把字段名变成键名,然后比较键名差异 -
性能方面
array_diff_key()比array_diff_assoc()快,因为只比较键名不比较值。如果只需要键名层面的差异,用这个函数效率更高。 -
键名严格匹配
键名比较是严格的:整数1和字符串"1"被认为是不同的键名。PHP数组内部会做类型转换,但比较时要注意。 -
对比array_diff_key和array_diff
下面的例子能看出区别:$a = ["x" => 1, "y" => 2, "z" => 3]; $b = ["x" => 100, "y" => 200]; array_diff($a, $b); // ["x" => 1, "y" => 2, "z" => 3] 值都不同,所以全部返回 array_diff_key($a, $b); // ["z" => 3] 只有z的键名不在b中
示例4:代码号学习编程场景
<?php
// 检查学生的选课记录是否有字段缺失
$expected_schema = [
"student_id" => null,
"course_name" => null,
"score" => null,
"semester" => null,
"teacher" => null
];
$actual_record = [
"student_id" => "code001",
"course_name" => "PHP基础",
"score" => 87
// 缺少 semester 和 teacher
];
$missing_keys = array_diff_key($expected_schema, $actual_record);
$extra_keys = array_diff_key($actual_record, $expected_schema);
echo "缺失的字段:\n";
print_r($missing_keys);
echo "\n多余的字段:\n";
print_r($extra_keys);
?>
输出:
缺失的字段:
Array
(
[semester] =>
[teacher] =>
)
多余的字段:
// 实际记录中没有多余字段,所以空数组
示例5:键名存在但类型不同
<?php
$arr1 = [1 => "苹果", "2" => "香蕉", 3 => "橙子"];
$arr2 = ["1" => "苹果", 2 => "香蕉", 3 => "橙子"];
// 注意:1 vs "1" 在键名比较中
$diff = array_diff_key($arr1, $arr2);
print_r($diff);
?>
输出:
Array
(
[1] => 苹果
[2] => 香蕉
)
这里有点绕:
-
arr1中键名1(整数)和arr1中键名1(整数)和arr2中键名"1"(字符串)被认为是不同的
-
arr1中键名"2"(字符串)和arr1中键名"2"(字符串)和arr2中键名2(整数)被认为是不同的
-
只有键名3(整数)两者相同,被排除
示例6:验证必要的数组键名
<?php
function validate_array_keys($data, $required_keys) {
$data_keys = array_keys($data);
$missing = array_diff($required_keys, $data_keys);
if (!empty($missing)) {
return ["valid" => false, "missing" => $missing];
}
return ["valid" => true, "missing" => []];
}
$user_data = [
"username" => "代码号001",
"email" => "user@test.com"
// 缺少 password
];
$required = ["username", "email", "password"];
$result = validate_array_keys($user_data, $required);
print_r($result);
?>
输出:
Array
(
[valid] =>
[missing] => Array
(
[2] => password
)
)
本节课程知识要点
-
array_diff_key()只比较数组的键名,不关心值 -
返回第一个数组中存在但其他数组中不存在的键名及其对应的值
-
支持两个以上的数组进行对比
-
和
array_diff()的区别:后者只比较值 -
和
array_diff_assoc()的区别:后者同时比较键名和值 -
键名比较时区分类型(整数和字符串视为不同)
-
从PHP 5.1开始可用