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']
==),比如 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+):
$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() 处理上万条数据,容易触发内存溢出或超时array_key_first()/array_key_last() 辅助判断,但不直接解决去重逻辑DISTINCT 或 Redis SET 结构预处理array_unique() 完全失效,硬套导致逻辑 bug;还有就是类型混用(比如 id 字段有时是 int 有时是 string)让松散比较误判重复。这些得在输入层就做归一化。