← PHP array_udiff_assoc函数教程:用自定义回调同时比较键名与值求差集 PHP array_udiff_uassoc函数:PHP键值双重回调数组差集运算 →

PHP array_udiff函数:PHP数组差集运算与自定义回调比较

著
原创 2026-10-09 PHP 已有人查阅

在PHP的数组函数体系中,array_udiff()属于差集运算家族中比较特殊的一个。它不依赖PHP内置的比较规则,而是把比较逻辑交给开发者自定义的回调函数。这个函数从PHP5.1.0开始提供,适合处理那些用默认比较方式无法满足需求的场景,比如对象数组、大小写敏感度需要控制的字符串数组,或者需要按特定业务规则判断“相等”的数据。

语法与参数说明

array array_udiff(
    array $array1,
    array $array2,
    [, array $... ],
    callable $value_compare_func
);

参数含义如下:

参数 说明 是否必须
array1 基准数组,差集运算以此数组为起点 是
array2 参与比较的数组 是
array3,... 更多参与比较的数组 否
value_compare_func 用户自定义的比较回调函数 是

回调函数的签名要求是:接收两个参数,返回一个整数。如果第一个参数小于第二个参数,返回小于0的整数;相等返回0;大于返回大于0的整数。这一点和strcmp()的返回逻辑一致。

返回值与键名处理

array_udiff()返回一个数组,包含所有在array1中但不在其他任何数组中的元素。这里有一个容易被忽略的细节:返回结果会保留array1中的键名。这意味着如果array1是关联数组,返回的数组也是关联数组,键名原样保留。

为什么需要自定义回调

PHP本身有array_diff()、array_diff_assoc()等函数,它们用PHP默认的字符串比较规则来判断元素是否相等。但在项目中,经常遇到以下情况:

  • 数组元素是对象,需要按对象某个属性来判断是否相等

  • 字符串比较需要区分大小写,或者需要忽略大小写

  • 数值比较需要按精度处理,比如浮点数保留两位小数后再比较

  • 业务上“相等”的定义不是值相等,而是某个标识符相等

这些场景下,array_udiff()的回调机制就派上了用场。

代码号学习编程:基础示例

先看一个最简单的例子,理解回调函数的工作方式。

<?php
function compareValues($a, $b)
{
    if ($a === $b) {
        return 0;
    }
    return ($a > $b) ? 1 : -1;
}

$array1 = ["a" => "C", "b" => "C++", "d" => "Java", "r" => "HTML"];
$array2 = ["a" => "C", "y" => "C++", "d" => "C#", "x" => "PHP"];

$result = array_udiff($array1, $array2, "compareValues");
print_r($result);

输出:

Array
(
    [d] => Java
    [r] => HTML
)

array1中的"C"和"C++"在array2中存在,所以被排除。"Java"和"HTML"不在array2中,保留下来。注意键名d和r被保留。

多个数组参与比较

array_udiff()支持同时比较两个以上的数组。只要某个元素在任意一个后续数组中出现,就会被排除。

<?php
function compareValues($a, $b)
{
    if ($a === $b) {
        return 0;
    }
    return ($a > $b) ? 1 : -1;
}

$lang1 = ["a" => "javatpoint", "b" => "c", "c" => "ruby", "php"];
$lang2 = ["A" => "javatpoint", "b" => "C", "php", "python"];
$lang3 = ["a" => "c", "b" => "javatpoint", "php", "python"];

$result = array_udiff($lang1, $lang2, $lang3, "compareValues");
print_r($result);

输出:

Array
(
    [c] => ruby
)

javatpoint在lang2和lang3中都出现,排除。c在lang3中出现,排除。php在lang2和lang3中都出现,排除。只有ruby在所有后续数组中都不存在。

项目实战反思:一个踩坑经历

早期做电商项目时,需要对比两个商品SKU列表,找出新增的SKU。SKU数据是从两个不同接口获取的,结构不一致,但都有一个sku_code字段可以唯一标识。

最初用了array_diff(),结果发现它比较的是整个数组元素的字符串表示,而两个接口返回的数组结构不同,比较结果不可用。后来改用array_udiff(),在回调里只比较sku_code:

<?php
function compareSku($a, $b)
{
    return strcmp($a['sku_code'], $b['sku_code']);
}

$oldSkus = [
    ['sku_code' => 'A001', 'name' => '商品A'],
    ['sku_code' => 'A002', 'name' => '商品B'],
];

$newSkus = [
    ['sku_code' => 'A002', 'name' => '商品B'],
    ['sku_code' => 'A003', 'name' => '商品C'],
];

$added = array_udiff($newSkus, $oldSkus, 'compareSku');
print_r($added);

输出:

Array
(
    [1] => Array
        (
            [sku_code] => A003
            [name] => 商品C
        )
)

这里有一个关键点:回调函数必须返回整数,不能返回布尔值。strcmp()正好满足这个要求。如果自己写比较逻辑,记得用===判断相等,用三元运算符返回1或-1。

另一个坑是键名保留。当时把array_udiff()的结果直接传给前端,前端按索引取值,结果因为键名不连续导致数据错乱。后来加了一步array_values()重新索引,问题才解决。所以如果后续代码依赖连续数字索引,记得手动处理。

个人建议:什么时候用,什么时候不用

array_udiff()的回调机制灵活,但性能上比array_diff()要差一些,因为每个元素都要经过用户函数调用。如果只是简单的字符串或数值比较,直接用array_diff()更高效。

适合用array_udiff()的场景:

  • 对象数组按属性比较

  • 多维数组按某个字段比较

  • 需要自定义相等规则的业务逻辑

  • 大小写敏感或需要忽略大小写的比较

不适合的场景:

  • 简单的标量数组差集,用array_diff()即可

  • 需要保留键名关联的差集,考虑array_diff_assoc()

  • 数据量极大且对性能敏感,考虑先用哈希表预处理再比较

本节课程知识要点

  • array_udiff()用回调函数比较数组元素,计算第一个数组与其他数组的差集

  • 回调函数必须返回整数,小于0、等于0、大于0分别表示小于、等于、大于

  • 返回结果保留第一个数组的键名,必要时用array_values()重新索引

  • 支持两个以上数组同时比较,元素在任意后续数组中出现即被排除

  • 适合对象数组、多维数组、自定义相等规则的场景,简单标量比较优先用array_diff()

进阶示例:大小写不敏感比较

<?php
function compareCaseInsensitive($a, $b)
{
    $a = strtolower($a);
    $b = strtolower($b);
    if ($a === $b) {
        return 0;
    }
    return ($a > $b) ? 1 : -1;
}

$array1 = ["Apple", "Banana", "Cherry"];
$array2 = ["apple", "banana", "date"];

$result = array_udiff($array1, $array2, "compareCaseInsensitive");
print_r($result);

输出:

Array
(
    [2] => Cherry
)

Apple和Banana在忽略大小写后与array2中的元素相等,被排除。Cherry不在array2中,保留。

这个例子展示了回调函数的灵活性:比较规则由开发者决定,array_udiff()只负责遍历和筛选。

array_udiff()是PHP数组差集函数中比较强大但容易被忽视的一个。它的价值在于把比较逻辑开放给开发者,让差集运算不再局限于PHP内置的字符串比较规则。理解回调函数的返回值约定、键名保留特性以及性能边界,能在项目中更准确地选用这个函数。

← PHP array_udiff_assoc函数教程:用自定义回调同时比较键名与值求差集 PHP array_udiff_uassoc函数:PHP键值双重回调数组差集运算 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号