给你两个数组,你想知道第一个数组里有哪些值是第二个数组没有的。array_diff()就是干这个的——它比较两个或多个数组的值,返回在第一个数组里存在、但在其他数组里不存在的那些条目。
注意:它只比较值,不关心键名是什么。这个函数从PHP 4.0就有了。
语法格式
array_diff(array $array1, array $array2 [, array $... ]): array
参数说明:
| 参数 | 说明 | 必填? |
|---|---|---|
| array1 | 作为基准的数组 | 必填 |
| array2 | 用来对比的数组 | 必填 |
| array3... | 更多用来对比的数组 | 可选 |
返回值: 返回一个数组,包含所有在array1中但不在其他数组中的元素。原数组的键名会保留。
核心规则
-
只比较值,键名是什么无所谓
-
字符串比较是区分大小写的
-
元素类型也会参与比较,整数的1和字符串的"1"不一样
示例1:基础用法
<?php
$intory_online = ["键盘", "鼠标", "显示器", "耳机", "摄像头"];
$intory_offline = ["键盘", "鼠标", "显示器"];
$only_online = array_diff($intory_online, $intory_offline);
print_r($only_online);
?>
输出:
Array
(
[3] => 耳机
[4] => 摄像头
)
耳机和摄像头只在线上仓库有,线下没有,所以返回来了。键名保留了原来的3和4。
示例2:多个数组比较
<?php
$all_students = ["张伟", "李芳", "王磊", "赵敏", "刘强", "陈晨"];
$class_a = ["张伟", "李芳"];
$class_b = ["王磊", "赵敏"];
$not_in_any_class = array_diff($all_students, $class_a, $class_b);
print_r($not_in_any_class);
?>
输出:
Array
(
[4] => 刘强
[5] => 陈晨
)
只要值出现在任何一个对比数组中,就会被排除。刘强和陈晨既不在A班也不在B班,所以返回。
示例3:区分大小写
<?php
$input = ["PHP", "JavaScript", "python", "Java"];
$reference = ["php", "JavaScript", "Python"];
$diff = array_diff($input, $reference);
print_r($diff);
?>
输出:
Array
(
[0] => PHP
[2] => python
[3] => Java
)
"PHP"和"php"不一样(大小写不同),所以"PHP"被保留了。"python"和"Python"也不一样。"Java"在参考数组里没有。只有"JavaScript"匹配被排除了。
个人经验分享
-
array_diff()、array_diff_assoc()、array_diff_key()的区别
| 函数 | 比较什么 | 什么时候用 |
|---|---|---|
| array_diff() | 只比较值 | 只关心哪些值没出现,键名不重要 |
| array_diff_key() | 只比较键名 | 想找出哪些键名是新出现的 |
| array_diff_assoc() | 键名+值都看 | 需要严格匹配键值对 |
举个例子你就明白了:
$a = ["id" => 1, "name" => "张伟", "score" => 85];
$b = ["id" => 1, "name" => "张伟", "score" => 90];
array_diff($a, $b); // ["score" => 85] 因为值85不在b中
array_diff_key($a, $b); // [] 键名都一样
array_diff_assoc($a, $b); // ["score" => 85] 键名相同但值不同
-
常见使用场景
-
找出两个列表的差异(比如新旧版本对比)
-
检查是否有新用户加入
-
数据去重前的准备工作
-
权限对比:用户有的权限vs角色默认权限
-
-
性能注意事项
array_diff()在处理大数组时效率还不错,但它是O(n*m)的时间复杂度。两个数组都是几万条的时候,运行时间会明显变长。如果数据量很大(几十万级别),建议用array_flip()加isset()的方案:$flip = array_flip($array2); $diff = array_filter($array1, function($value) use ($flip) { return !isset($flip[$value]); });这个方法更快,因为isset是O(1)的。
-
键名会被保留,但不一定连续
$result = array_diff(["a","b","c","d"], ["b","d"]); // 返回 [0 => "a", 2 => "c"] // 下标0和2,跳过了1如果后续需要连续索引,用
array_values()包一下:array_values($result)
示例4:代码号学习编程场景
<?php
// 两个学期选修课程的变化检测
$semester1_courses = ["PHP基础", "MySQL", "JavaScript", "Laravel", "Vue"];
$semester2_courses = ["PHP基础", "Python", "JavaScript", "Django"];
// 新课程(只在第二学期有)
$new_courses = array_diff($semester2_courses, $semester1_courses);
// 取消的课程(只在第一学期有)
$removed_courses = array_diff($semester1_courses, $semester2_courses);
// 保留的课程(两个学期都有)
$kept_courses = array_intersect($semester1_courses, $semester2_courses);
echo "新增课程:\n";
print_r($new_courses);
echo "\n取消课程:\n";
print_r($removed_courses);
echo "\n保留课程:\n";
print_r($kept_courses);
?>
输出:
新增课程:
Array
(
[1] => Python
[3] => Django
)
取消课程:
Array
(
[1] => MySQL
[3] => Laravel
[4] => Vue
)
保留课程:
Array
(
[0] => PHP基础
[2] => JavaScript
)
示例5:值相同但类型不同
<?php
$arr1 = [1, 2, "3", 4];
$arr2 = [1, "2", 3, 4];
$diff = array_diff($arr1, $arr2);
print_r($diff);
?>
输出:
Array
(
[1] => 2
[2] => 3
)
1(整数)匹配了1(整数),4匹配了4。但整数2和字符串"2"类型不同不匹配,字符串"3"和整数3类型不同不匹配。所以2和"3"被保留下来了。
本节课程知识要点
-
array_diff()只比较数组的值,忽略键名 -
支持两个以上的数组进行对比
-
返回第一个数组中存在、但其他数组中不存在的元素
-
保留原数组的键名,不重新索引
-
比较时区分大小写,也区分类型
-
和
array_diff_assoc()的区别:后者同时比较键名和值 -
从PHP 4.0开始可用