在 PHP 中,array_diff() 是一个非常常用的函数,能够找出数组之间的差异。但当我们在实际项目中使用它来处理(associative array)时,如果不理解它的工作原理,可能会踩到不少“坑”。
本文将深入讲解 array_diff() 在关联数组处理中的行为、常见误区,以及一些实用技巧。
$array1 = ['a' => 'apple', 'b' => 'banana', 'c' => 'cherry'];
$array2 = ['a' => 'apple', 'b' => 'blueberry'];
$result = array_diff($array1, $array2);
print_r($result);
输出:
Array
(
[b] => banana
[c] => cherry
)
解释: array_diff() 只比较“值”,而忽略键名。在这个例子中,虽然 $array1['b'] = 'banana' 和 $array2['b'] = 'blueberry' 的键一样,但由于值不同,因此 'banana' 被视为差异之一。
误区: 很多开发者以为 array_diff() 会比较键值对。
$a = ['id' => 1, 'name' => 'John'];
$b = ['name' => 'John', 'id' => 2];
var_dump(array_diff($a, $b));
输出:
array(1) {
["id"]=>
int(1)
}
虽然 'name' => 'John' 在两个数组中键和值都一样,但因为 array_diff() 不看键,它只关注值是否存在。所以 'id' => 1 因为 1 不在 $b 的值中,就被当作不同。
? 解决方法: 如果你想要同时比较键和值,建议使用 array_diff_assoc():
array_diff_assoc($a, $b);
它会同时比较键和值,能避免这种“错觉”。
$a = ['value1' => 123];
$b = ['value2' => '123'];
print_r(array_diff($a, $b));
输出:
Array
(
)
坑点: array_diff() 使用的是非严格比较(==),所以 123 和 '123' 被认为是相同的。
? 技巧: 如果你需要严格比较(值和类型都要一致),可以使用 array_diff() 的变体 array_diff_uassoc() 搭配自定义比较函数。
$result = array_udiff($a, $b, function($a, $b) {
return $a === $b ? 0 : ($a > $b ? 1 : -1);
});
array_diff() 是一维数组工具,对于多维数组,它不会递归比较。
$a = ['info' => ['id' => 1, 'name' => 'Tom']];
$b = ['info' => ['id' => 1, 'name' => 'Tom']];
print_r(array_diff($a, $b));
输出:
Array
(
[info] => Array
(
[id] => 1
[name] => Tom
)
)
原因: 数组类型的值在 array_diff() 中被当作字符串看待,它无法直接比较两个数组内容是否相等。
? 解决方案: 如果你想比较多维数组,需要手动写递归函数,或者使用序列化转换后比较:
$a_serialized = array_map('serialize', $a);
$b_serialized = array_map('serialize', $b);
$diff = array_diff($a_serialized, $b_serialized);
假设你从数据库拉出一条数据到 $original,用户提交了一个表单形成了 $new_data,你想知道哪些字段发生了变化:
$original = ['name' => 'Alice', 'email' => 'a@m66.net'];
$new_data = ['name' => 'Alice', 'email' => 'alice@m66.net'];
$changed = array_diff_assoc($new_data, $original);
这样你就可以精准获取哪些字段被用户更改了。
你有两个配置数组 $config1 和 $config2:
$config1 = include 'http://m66.net/config/old.php';
$config2 = include 'http://m66.net/config/new.php';
$diff = array_diff_assoc($config2, $config1);
这就可以方便地获取配置变更,尤其适合写在自动化脚本中。
方法 | 比较内容 | 是否区分类型 | 适合场景 |
---|---|---|---|
array_diff() | 只比较值 | 否 | 简单值的对比 |
array_diff_assoc() | 比较值 + 键名 | 否 | 表单、配置对比 |
array_udiff() | 自定义比较方式 | 可自定义 | 严格类型对比 |
serialize + array_diff() | 多维数组对比 | 否(可扩展) | 多维结构对比 |
使用 array_diff() 的时候,要清楚你到底在比较什么。不要被键名误导,也不要忘了类型的影响。理解这些原理,才能真正用好这个工具函数。
如果你在项目中遇到特殊的对比需求,欢迎动手写一个小工具函数封装逻辑——这样既提高了代码可读性,也减少了踩坑概率。