array_unique保留原始键名且不重排索引,需用array_values重置;默认松散比较易误删,多维数组不递归;不支持对象/资源;大数据量时性能较差,手写isset去重更快。

array_unique 会保留原始键名,不是重排索引
直接用 array_unique 去重后,数组的数字键可能不连续,比如 [0 => 'a', 2 => 'b', 5 => 'a'] 去重后变成 [0 => 'a', 2 => 'b'],而不是你想要的 [0 => 'a', 1 => 'b']。
- 如果后续要遍历、JSON 输出或传给前端,建议手动重置键:
array_values(array_unique($arr)) -
array_unique对字符串和整数默认按「松散比较」处理,'1'和1会被视为相同 —— 这在混合类型数组里容易误删 - 它不递归,多维数组每个子数组被当做一个整体比较,不会深入比对内部元素
去重时要注意 $sort_flags 参数的实际效果
array_unique 的第二个参数控制比较方式,但只影响「排序行为」,不影响去重逻辑本身;PHP 7.2+ 才支持该参数,低版本传了也无效。
-
SORT_STRING(默认):按字符串规则比较,0和'0'相同 -
SORT_REGULAR:按类型+值严格比较,0 !== '0',能避免类型混淆导致的误去重 -
SORT_NUMERIC:把所有值转为数字再比,'1'、1、1.0全算一样 —— 用前确认业务是否允许这种隐式转换
遇到对象或资源类型会报 Warning 并跳过
array_unique 不支持对象、资源、闭包等不可序列化类型,遇到时会触发 Warning: array_unique(): Array contains elements that cannot be compared,并把它们原样保留在结果中(不去重也不报错退出)。
- 若数组里混有对象,先用
array_map提取可比字段,例如:array_unique(array_column($arr, 'id')) - 想彻底过滤掉非标量值,得自己写循环 +
is_scalar()判断 - 注意:即使对象实现了
__toString(),也不会被自动调用用于比较
大数据量下性能明显下降,别无脑用
array_unique 底层是哈希去重,时间复杂度接近 O(n),但 PHP 实现中会做多次内部拷贝和类型判断,实测 10 万以上字符串元素时比手写 foreach + isset($seen[$v]) 慢 2–3 倍。
立即学习“PHP免费学习笔记(深入)”;
- 纯数值/字符串且确定无类型混杂,用这个更简洁:
$unique = [];$seen = []; foreach ($arr as $v) { if (!isset($seen[$v])) { $seen[$v] = true; $unique[] = $v; } } - 需要保持原始顺序又追求性能,上面的手写法比
array_unique更可控 - 如果只是校验“是否存在重复”,用
count($arr) !== count(array_unique($arr))就够,别为了判断还存结果
最常被忽略的是类型隐式转换和键名残留——尤其从数据库或 API 拿来的数据,看着是数字,实际是字符串,一去重就丢一半。动手前先 var_dump(array_slice($arr, 0, 3)) 看两眼类型。



















