array_unique() 是 PHP 一维数组去重的标准方法,但不支持多维数组;二维数组需按唯一字段(如 id)手动去重,或序列化哈希;PHP 8.3 新增严格模式 flag,注意版本兼容性。

array_unique() 是 PHP 数组去重的唯一标准解法
它能直接处理一维数组,对值去重并保留首次出现的键名。但注意:array_unique() 不会改变原数组,必须重新赋值;而且它只比较「值」,不递归处理多维数组。
常见错误是以为它能去重二维数组或对象数组——实际会报 Array to string conversion 警告,因为内部尝试把数组转成字符串做哈希比对。
- 字符串、数字混排时,
"1"和1默认会被视为相同(松散比较),加SORT_REGULAR可避免 - 关联数组去重后键名保留,但顺序可能打乱(底层用哈希表实现)
- 大数据量时性能尚可,但比纯索引数组慢约 20%~30%,因要维护键值映射
二维数组去重得自己写逻辑,别硬套 array_unique()
比如你有一组用户数据:[["id"=>1,"name"=>"a"],["id"=>2,"name"=>"b"],["id"=>1,"name"=>"a"]],想按 id 去重。这时 array_unique() 完全无效。
最稳妥的做法是用 foreach + isset() 检查已存在键:
立即学习“PHP免费学习笔记(深入)”;
$unique = [];
foreach ($data as $item) {
if (!isset($unique[$item['id']])) {
$unique[$item['id']] = $item;
}
}
注意:这种写法依赖某个唯一字段(如 id),如果没现成唯一键,就得用 serialize($item) 当哈希值,但要注意序列化开销和浮点数精度问题。
- 用
array_column()提取某列再配合array_unique()只能拿到去重后的值,丢键又丢整行数据 -
array_filter()配合闭包也能做,但可读性差、性能略低,不推荐日常用 - PHP 8.1+ 的
array_key_first()在某些遍历场景有用,但和去重无直接关系
去重后想重排键名?用 array_values() 就行
array_unique() 返回的数组键名是稀疏的(比如原数组键为 0,2,5,去重后还是这样)。如果后续要 json_encode() 或传给前端,常需要连续数字键。
直接包一层 array_values() 即可:
$clean = array_values(array_unique($arr));
但注意:这会丢失所有原始键名信息。如果你靠键名存业务含义(比如配置项名),就不能这么干。
-
array_values()是 O(n) 操作,几乎无性能负担 - 它不改变值本身,只重置键,和
array_unique()组合是安全的 - 别误用
array_merge([]...)来重排键——虽然效果一样,但语义不清且多一次函数调用
PHP 8.3 的 array_unique() 新增 flags 参数容易被忽略
新版支持 ARRAY_UNIQUE_STRICT 和 ARRAY_UNIQUE_LOOSE,显式控制类型比较方式。以前只能靠第三个参数传 SORT_STRING 等间接影响,现在更直白。
例如严格模式下,"1" 和 1 不再被当成重复项:
array_unique([1, "1", 2], ARRAY_UNIQUE_STRICT); // 返回 [1, "1", 2]
但要注意:这个 flag 在 PHP 8.3 才引入,线上环境低于该版本会 fatal error。检查版本不能只看 PHP_VERSION_ID,还得确认是否启用了新特性开关(某些 Docker 镜像默认关)。
- 升级前务必在测试环境验证旧代码行为是否变化
- CI 中加
php -v和php -r "var_dump(defined('ARRAY_UNIQUE_STRICT'));"双重校验 - 框架封装的“通用去重工具函数”如果没适配此 flag,很可能悄悄失效











