array_unique只对一维数组有效,多维数组因强制转字符串导致全被当作重复项;需json_encode后去重再json_decode;类型不统一时"1"和1被视为不同元素;去重后键名保留原序不重排。

array_unique 为什么对多维数组完全没反应
array_unique 只能处理一维数组,内部用字符串键做去重依据。遇到多维数组时,它会把每个子数组强制转成字符串(比如 Array),结果所有子数组都变成一样的字符串,最后只留第一个——看起来“没去重”,其实是全被当成重复项删了。
常见错误现象:
输入是 [['a'=>1], ['a'=>1], ['b'=>2]],输出还是原样,或只剩第一个元素。
- 解决办法:先用
json_encode把每行转成唯一字符串,去重后再json_decode - 注意:要加
JSON_UNESCAPED_UNICODE避免中文被编码,否则可能误判为不同项 - 如果数组含资源、闭包或循环引用,
json_encode会失败,得换serialize(但性能差些)
array_unique 对字符串数字和整数不识别为相同值
默认情况下,array_unique 使用 string 比较规则,"1" 和 1 被视为两个不同元素。这不是 bug,是设计如此——它不做类型转换。
使用场景:从 $_GET 或数据库查出的混合类型 ID 列表,容易残留字符串型数字。
- 临时修复:用
array_map('intval', $arr)或array_map('strval', $arr)统一类型再调用array_unique - 更稳妥:用
SORT_REGULAR参数无效,真正起作用的是SORT_STRING(默认)或SORT_NUMERIC—— 但注意,SORT_NUMERIC只影响排序行为,不去重逻辑本身仍基于字符串键 - 结论:类型统一必须手动做,
array_unique不替你判断语义相等性
array_unique 后键名乱序、缺失导致 foreach 出错
去重后数组保留原始键名,不是重排索引。比如 [0=>'a', 2=>'a', 1=>'b'] 去重得 [0=>'a', 1=>'b'],看着正常;但若原数组是 [5=>'x', 10=>'x', 3=>'y'],结果就是 [5=>'x', 3=>'y'] —— 键不连续,直接 for($i=0; $i<count> 会漏数据。</count>
- 需要重索引时,套一层
array_values():array_values(array_unique($arr)) - 如果后续要
array_merge或传给某些函数(如implode),不重索引一般不影响;但涉及键敏感操作(如$arr[0]直接取值)就必须处理 - 注意:重索引会丢弃原始键名,如果业务依赖键名(如关联字段名),不能无脑
array_values
PHP 8.3+ 中 array_unique 的 strict 模式还没来
目前所有 PHP 版本的 array_unique 都没有类似 JavaScript Set 那样的严格相等(===)选项。所谓“严格”只存在于文档误解里——它的比较始终是松散的字符串化过程。
如果你真需要基于类型 + 值的精确去重(比如区分 0、false、''、null),array_unique 无法胜任。
- 替代方案:手写循环 +
in_array($item, $seen, true),第三个参数true开启严格比较 - 性能提醒:大数组慎用
in_array(..., true),复杂度 O(n²);可改用array_flip构建查找表(但要求元素可作为键,即必须是标量且非 float) - 最易忽略的一点:很多人以为加了
SORT_*参数就能改变去重逻辑,其实不能——那些参数只控制排序顺序,不影响去重判定本身
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











