array_diff()只比较数组的值,不关心键名。但有时候你需要严格一点——键名和值都要匹配才算相同。
array_diff_assoc()就是干这个的:比较两个或更多数组的键名和值,返回在第一个数组中存在、但在其他数组中不存在的条目(键名+值都算在内)。
语法格式
array_diff_assoc(array $array1, array $array2 [, array $... ]): array
参数说明:
| 参数 | 说明 | 必填? |
|---|---|---|
| array1 | 要比较的原始数组 | 必填 |
| array2 | 用来对比的数组 | 必填 |
| array3... | 更多用来对比的数组 | 可选 |
返回值: 返回一个数组,包含所有在array1中存在但不在其他数组中的键值对。
和array_diff的区别
| 函数 | 比较内容 | 使用场景 |
|---|---|---|
| array_diff() | 只看值 | 不关心键名,只统计哪些值没出现 |
| array_diff_assoc() | 键名+值都看 | 需要严格区分键名不同的情况 |
示例1:基础用法
<?php
$intory1 = [
"sku001" => "键盘",
"sku002" => "鼠标",
"sku003" => "显示器",
"sku004" => "耳机"
];
$intory2 = [
"sku001" => "键盘",
"sku002" => "鼠标",
"sku005" => "摄像头"
];
$diff = array_diff_assoc($intory1, $intory2);
print_r($diff);
?>
输出:
Array
(
[sku003] => 显示器
[sku004] => 耳机
)
注意:虽然intory1里的"键盘"和"鼠标"的值在intory2里也存在,但键名匹配上了(sku001和sku002都一致),所以没有被列入差集。而"显示器"和"耳机"在intory2里没有对应的键名+值,所以返回。
示例2:键名相同但值不同
<?php
$student_scores_1 = [
"code001" => 85,
"code002" => 92,
"code003" => 78
];
$student_scores_2 = [
"code001" => 85,
"code002" => 88, // 值不同
"code003" => 78
];
$diff = array_diff_assoc($student_scores_1, $student_scores_2);
print_r($diff);
?>
输出:
Array
(
[code002] => 92
)
code002在两个数组中的值不同(92 vs 88),所以被算作差集返回。
示例3:键名不同但值相同
<?php
$fruit_basket_a = [
"a1" => "苹果",
"a2" => "香蕉",
"a3" => "橙子"
];
$fruit_basket_b = [
"b1" => "苹果",
"b2" => "橙子",
"b3" => "香蕉"
];
$diff = array_diff_assoc($fruit_basket_a, $fruit_basket_b);
print_r($diff);
?>
输出:
Array
(
[a1] => 苹果
[a2] => 香蕉
[a3] => 橙子
)
惊讶吗?三个元素全返回了。虽然值都在第二个数组里存在,但键名不一样。array_diff_assoc要求键名和值同时相等才算匹配。这里a1和b1键名不同,所以不匹配。
个人经验分享
-
什么时候用array_diff_assoc而不是array_diff?
-
处理关联数组,键名有实际意义(比如用户ID、商品编码)
-
需要严格区分相同值的不同键名
-
同步两个配置数组时,想找出具体哪个配置项变了
-
-
实际场景:对比配置变更
$old_config = ["db_host" => "localhost", "db_name" => "old_db", "cache" => "redis"]; $new_config = ["db_host" => "localhost", "db_name" => "new_db", "cache" => "redis"]; $changes = array_diff_assoc($new_config, $old_config); // 返回 ["db_name" => "new_db"],只有变更的项 -
多维数组的限制
array_diff_assoc()处理多维数组时,只能比较第一层。嵌套的子数组会被整体当作一个元素比较,不会递归比较内部。需要递归比较的话,自己写递归函数或者用array_udiff_assoc()配合自定义回调。 -
性能考虑
这个函数比较的是两个数组的差值,时间复杂度大致是O(n*m)。两个数组都很大的时候(比如各几万条),运行时间会明显增加。大数据量下考虑用数据库操作或者算法优化。
示例4:多个数组比较
<?php
$team_a = ["id1" => "张伟", "id2" => "李芳", "id3" => "王磊", "id4" => "赵敏"];
$team_b = ["id1" => "张伟", "id2" => "刘强"];
$team_c = ["id3" => "王磊", "id5" => "陈晨"];
$unique_to_a = array_diff_assoc($team_a, $team_b, $team_c);
print_r($unique_to_a);
?>
输出:
Array
(
[id4] => 赵敏
)
只有在team_a中存在,且在team_b和team_c中都不存在的条目才会返回。id1虽然值匹配,但键名也匹配上了所以排除;id3的值在team_c中出现了,键名也匹配上了所以排除;只有id4是独有的。
示例5:代码号学习编程场景
<?php
// 两个学期的选课记录对比
$semester1 = [
"code001" => "PHP基础",
"code002" => "MySQL教程",
"code003" => "JavaScript入门",
"code004" => "Laravel框架"
];
$semester2 = [
"code001" => "PHP基础",
"code002" => "Python基础", // 换课了
"code003" => "JavaScript入门",
"code005" => "数据结构" // 新学生
];
// 找出哪些学生换课了(键名相同但值不同)
$changed = array_diff_assoc($semester1, $semester2);
// 找出退课的学生(在semester1中有但在semester2中没有)
$dropped = array_diff_key($semester1, $semester2);
// 找出新选课的学生(在semester2中有但在semester1中没有)
$new = array_diff_key($semester2, $semester1);
echo "换课的学生:\n";
print_r($changed);
echo "\n退课的学生:\n";
print_r($dropped);
echo "\n新选课的学生:\n";
print_r($new);
?>
示例6:索引数组的
<?php
$arr1 = ["红", "绿", "蓝"];
$arr2 = ["绿", "红", "蓝"];
$diff = array_diff_assoc($arr1, $arr2);
print_r($diff);
?>
输出:
Array
(
[0] => 红
[1] => 绿
)
索引数组也是基于键名比较的。arr1[0]="红"和arr1[0]="红"和arr2[0]="绿"不匹配,arr1[1]="绿"和arr1[1]="绿"和arr2[1]="红"不匹配,所以前两个都返回。如果只想按值比较,用array_diff()。
本节课程知识要点
-
array_diff_assoc()比较多个数组的键名+值,返回只存在于第一个数组的条目 -
和
array_diff()的区别:后者只比较值,忽略键名 -
键名相同但值不同的条目会被算作差集返回
-
键名不同但值相同的条目也会被算作差集返回
-
支持传入多个数组进行对比
-
多维数组只比较第一层,不递归
-
从PHP 4.3开始可用