array_unique 不会改变原数组,而是返回新数组;对关联数组保留键名;默认大小写敏感,需预处理;不支持多维数组;大数据量时可分块或改用 array_flip 优化。

array_unique 会改变原数组吗
不会。它总是返回一个新数组,原数组保持不变——这点和 sort、array_splice 这类就地修改的函数不同。
常见误操作是写成:$arr = array_unique($arr),以为在“去重”,其实只是把结果重新赋值给了同名变量。这本身没问题,但如果你还依赖原数组后续使用(比如做对比或日志),就得注意别覆盖了。
实操建议:
- 需要保留原数组时,务必用新变量接收结果,比如
$unique_arr = array_unique($arr) - 如果原数组很大且确定不再需要,赋值回原变量也行,但得清楚这是「替换」而非「修改」
- 对关联数组使用时,键名会被保留(只删重复值对应的后出现的键),不是按数字索引重排
字符串大小写敏感怎么处理
array_unique 默认完全按值比较,"Apple" 和 "apple" 被视为两个不同元素。没有内置参数开关来忽略大小写。
必须自己预处理。最稳妥的做法是在调用前统一转小写(或大写),但要注意:你丢掉了原始大小写的值。
实操建议:
- 若只需去重且不关心原始大小写,先用
array_map('strtolower', $arr)再传给array_unique - 若要保留原始值(比如显示用),得用
array_column+array_unique配合array_intersect_key回捞,例如:$lowered = array_map('strtolower', $arr); $unique_keys = array_unique($lowered); $result = array_intersect_key($arr, $unique_keys); - 避免用
strcasecmp自定义回调——array_unique不接受比较函数,PHP 8.3 之前都不支持
多维数组为什么不能直接用 array_unique
因为 array_unique 只能处理一维数组。遇到二维或更高维时,会把整个子数组当作一个值去比较,而 PHP 中数组不能作为 key 或直接参与松散比较,结果通常是所有元素都被判为“不重复”或触发警告(如 Array to string conversion)。
错误现象:输入 [["a",1], ["a",1]],输出还是原样;或者报 Notice: Array to string conversion,并返回奇怪结果。
实操建议:
- 想按某列去重(如 ID 字段),用
array_column提取该列,再用array_unique得到唯一键,最后array_intersect_key拿回原数组项 - 想完全按内容去重,需先
json_encode每个子数组,去重后再json_decode—— 注意浮点数精度和对象/资源无法编码的问题 - 不要尝试用
SPLFixedArray或foreach手动遍历模拟,性能差且易漏边界(比如空数组、null 值)
性能差的时候该怎么优化
当数组超过几万项,array_unique 可能明显变慢。它内部用哈希表实现,理论上 O(n),但实际受哈希碰撞、内存分配、值序列化开销影响较大——尤其含长字符串或嵌套结构时。
关键瓶颈常不在算法本身,而在 PHP 对值的拷贝和哈希计算方式。
实操建议:
- 确认是否真需要全量去重:能否用数据库
DISTINCT或缓存层提前过滤? - 如果只是判断“是否存在重复”,用
count($arr) !== count(array_unique($arr))效率低,改用array_flip+count更快(但仅限字符串/整数键) - 对超大数组,分块处理(比如每 5000 项一批),用
array_merge合并结果前先去重中间结果,减少最终合并量 - PHP 8.1+ 可考虑
array_unique($arr, SORT_REGULAR)显式指定模式,避免隐式类型转换带来的额外开销
真正麻烦的是带 null、NaN、对象、资源的数组——这些值在 array_unique 里行为不一致,甚至不可预测。动手前先 var_dump 看清数据结构,比查文档更快定位问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











