17370845950

php代码示例如何实现数组去重_php数组去重代码示例及说明【示例】
array_unique()去重保留首个值键名,需array_values()重索引;仅支持标量,二维数组须手动序列化或按字段提取;默认松散比较,PHP 8.2+支持flags严格控制;大数据量应避免serialize/json_encod

e,优先数据库或Redis处理。

array_unique() 去重最直接,但要注意键名保留规则

array_unique() 是 PHP 内置函数,处理一维数组去重最常用。它会保留**第一个出现的值对应键名**,后续重复值的键会被丢弃,而不是简单重排索引。

常见错误是以为返回数组索引一定从 0 开始连续——实际不会,得手动用 array_values() 重置:

$arr = ['a', 'b', 'a', 'c'];
$result = array_unique($arr);
// $result = [0 => 'a', 1 => 'b', 3 => 'c'] —— 键 2 被跳过
$result = array_values($result); // [0 => 'a', 1 => 'b', 2 => 'c']
  • 只支持标量值(string、int、float、bool),对含数组或对象的元素会报 Warning 并跳过比较
  • 默认使用松散比较(==),比如 0'0' 被视为重复;如需严格比较,加第二个参数 ARRAY_FILTER_USE_KEY 不适用,正确选项是 SORT_REGULAR(默认)、SORT_STRINGSORT_NUMERIC,但注意:PHP 8.2+ 才支持 flags 参数控制比较方式,老版本只能靠预处理统一类型

二维数组去重必须自己写逻辑,array_unique() 无效

array_unique() 对二维数组直接返回原数组,因为内部用字符串化比较,而数组转字符串结果都是 "Array",所有行都“相同”。必须手动序列化 + 去重 + 反序列化,或用 foreach + in_array()(小数据)。

推荐方案(兼容 PHP 7.4+):

$arr2d = [['id'=>1,'name'=>'A'], ['id'=>2,'name'=>'B'], ['id'=>1,'name'=>'A']];
$seen = [];
$unique = [];

foreach ($arr2d as $item) {
    $key = md5(serialize($item)); // 或用 json_encode($item, JSON_UNESCAPED_UNICODE)
    if (!isset($seen[$key])) {
        $seen[$key] = true;
        $unique[] = $item;
    }
}
  • 不用 json_encode() 时注意浮点数精度和 NaN 行为;用 serialize() 更稳妥,但结果不可读
  • 如果只按某个字段(如 id)去重,可用 array_column() 提取后配合 array_unique(),再用 array_intersect_key() 还原原数组
  • 大数据量别用 in_array($item, $unique) 做判断,时间复杂度 O(n²),务必用哈希键(如上面的 $seen

保留最后出现的重复项?array_unique() 不支持,得反转再反转

默认 array_unique() 保留首次出现项。若要保留最后一次,常见做法是先 array_reverse(),去重,再反转回来:

$arr = ['a', 'b', 'a', 'c', 'b'];
$reversed = array_reverse($arr);
$unique_reversed = array_unique($reversed);
$result = array_reverse($unique_reversed); // ['c', 'b', 'a']
  • 注意:这会改变原始键名顺序,且数值键会变成字符串键(因 array_reverse() 默认保留键名,但反转后数字键可能不连续,建议加第三个参数 true 强制重索引)
  • 更可控的方式是遍历倒序,用键存在性检查:if (!isset($unique[$item])) { $unique[$item] = $item; },最后用 array_values($unique)

性能敏感场景慎用 serialize()json_encode()

对大数组做去重时,serialize()json_encode() 都有明显 CPU 和内存开销。如果数组结构固定(如都是关联数组且字段已知),可拼接关键字段生成唯一 hash:

// 比如只看 'id' 和 'status'
$key = $item['id'] . '|' . $item['status'];
  • 避免在循环内反复调用 serialize() 处理上万条数据,容易触发内存溢出或超时
  • PHP 8.1+ 可考虑用 array_key_first()/array_key_last() 辅助判断,但不直接解决去重逻辑
  • 真正大批量(如 >10 万)建议移出 PHP,用数据库 DISTINCT 或 Redis SET 结构预处理
实际项目里最容易被忽略的是:二维数组去重时没意识到 array_unique() 完全失效,硬套导致逻辑 bug;还有就是类型混用(比如 id 字段有时是 int 有时是 string)让松散比较误判重复。这些得在输入层就做归一化。