array_unique()去重保留首个值键名,需array_values()重索引;仅支持标量,二维数组须手动序列化或按字段提取;默认松散比较,PHP 8.2+支持flags严格控制;大数据量应避免serialize/json_encode,优先数据库或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_STRING或SORT_NUMERIC,但注意:PHP 8.2+ 才支持flags参数控制比较方式,老版本只能靠预处理统一类型
二维数组去重必须自己写逻辑,array_unique() 无效
array_unique() 对二维数组直接返回原数组,因为内部用字符串化比较,而数组转字符串结果都是 "Array",所有行都“相同”。必须手动序列化 + 去重 + 反序列化,或用 foreach + in_array()(小数据)。
推荐方案(兼容 PHP 7.4+):
《PHP设计模式》首先介绍了设计模式,讲述了设计模式的使用及重要性,并且详细说明了应用设计模式的场合。接下来,本书通过代码示例介绍了许多设计模式。最后,本书通过全面深入的案例分析说明了如何使用设计模式来计划新的应用程序,如何采用PHP语言编写这些模式,以及如何使用书中介绍的设计模式修正和重构已有的代码块。作者采用专业的、便于使用的格式来介绍相关的概念,自学成才的编程人员与经过更多正规培训的编程人员
立即学习“PHP免费学习笔记(深入)”;
$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或 RedisSET结构预处理
array_unique() 完全失效,硬套导致逻辑 bug;还有就是类型混用(比如 id 字段有时是 int 有时是 string)让松散比较误判重复。这些得在输入层就做归一化。










