array_unique无法直接对二维数组去重,因其将整行转为字符串比较;正确方法是用目标字段作键,利用数组键唯一性自动覆盖,如$temp[$item['name']] = $item; $unique = array_values($temp)。

用 array_unique 直接去重行不通
PHP 的 array_unique 默认只支持一维数组或简单值比较,对二维数组会把整行当字符串处理(比如 Array),结果永远返回原数组——它根本没真正比较字段内容。
常见错误现象:调用 array_unique($arr, SORT_REGULAR) 后数组长度没变,或者去重逻辑完全不符合预期。
真正可行的思路是:提取目标字段构成索引键,利用 PHP 数组键唯一性自动覆盖重复项。
- 适合中小规模数据(几千条以内),代码简洁、可读性强
- 不修改原数组结构,只是“选”出不重复的行
- 注意字段值不能为
null、array或object,否则作为键会强制转成""或0,导致误合并
按单个字段去重:用 array_column + array_combine
这是最常用也最稳妥的方式,核心是让目标字段值成为新数组的键,再用 array_values 重置索引。
$unique = array_values(array_unique(array_column($arr, 'name'), SORT_STRING)); // ❌ 错!上面只取出了 'name' 字段值,丢了整行数据
正确写法:
$temp = [];
foreach ($arr as $item) {
$key = $item['name']; // 指定去重字段
$temp[$key] = $item; // 键重复时自动覆盖
}
$unique = array_values($temp);
- 字段名必须存在且可直接访问,否则会触发
Notice: Undefined index - 如果想保留第一次出现的项(而非最后一次),需加判断:
if (!isset($temp[$key])) { $temp[$key] = $item; } - 若字段值含特殊字符或大小写敏感需求,可提前用
strtolower或md5归一化
按多个字段联合去重:拼接键或序列化
需要同时看 user_id 和 status 才算重复?不能简单用一个字段做键,得构造复合键。
推荐拼接方式(轻量、可读):
$temp = [];
foreach ($arr as $item) {
$key = $item['user_id'] . '|' . $item['status'];
$temp[$key] = $item;
}
$unique = array_values($temp);
更健壮但稍重的方式(处理 null / 数组等边界):
$key = serialize([$item['user_id'], $item['status']]);
- 拼接符(如
|)要确保不会出现在字段值中;若不确定,改用serialize更安全 -
serialize生成的键较长,内存占用略高,但兼容所有类型(除资源) - 避免用
json_encode做键——浮点数精度、数组顺序可能影响一致性
性能和兼容性提醒
PHP 7.4+ 可用箭头函数简化,但实际性能提升微乎其微;重点还是逻辑清晰和字段可靠性。
- 超大数组(>10 万行)慎用此方法,考虑数据库层去重或分块处理
- 如果二维数组里有引用或对象,
$temp[$key] = $item是浅拷贝,原引用关系仍存在 - 字段名带空格或特殊符号?先用
str_replace清洗,或改用数字索引 + 映射表
最容易被忽略的是字段值类型隐式转换——比如 '1' 和 1 当作同一键,但业务上可能是不同含义。动手前先 var_dump(array_column($arr, 'field')) 看一眼真实值类型。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











