最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
PHP函数array_unique对多维数组失效的解决方案:去重算法
时间:2026-07-12 09:12:03 编辑:袖梨 来源:一聚教程网
array_unique对多维数组无效,因其内部用==比较数组失败而静默保留原数组;推荐serialize+array_unique组合去重,或按字段用array_filter+$seen哈希表高效处理。
array_unique对多维数组直接调用会返回原数组
它根本不会去重,也不报错,只是静默跳过所有子数组——因为 PHP 内部尝试用 == 比较两个数组时失败,最终把整个子数组当“不可比”处理,原样保留。你看到的“没变化”,不是函数卡住,而是设计如此。
常见错误现象:array_unique([['id'=>1], ['id'=>1]]) 返回原数组;array_unique($multi, SORT_REGULAR) 也无效;PHP 8.3 依然不支持。
- 别指望加
$flags参数能起作用——多维数组本身就不在array_unique的支持范围内 - 如果数组里混有
null、对象或资源,还会触发Warning: Array to string conversion - 错误日志里可能只显示 “Array to string conversion”,但实际是去重逻辑被绕过了
用 serialize + array_unique 是最简方案
把每个子数组转成唯一字符串再比,绕过类型限制。这是目前最通用、兼容性最好的做法,PHP 5.6 到 8.3 全支持。
示例代码:
立即学习“PHP免费学习笔记(深入)”;
$multi = [['id'=>1,'name'=>'Alice'], ['id'=>1,'name'=>'Alice'], ['id'=>2,'name'=>'Bob']];$unique = array_map('unserialize', array_unique(array_map('serialize', $multi)));
-
array_map('serialize', $multi)把每个子数组变成字符串,如a:2:{s:2:"id";i:1;s:4:"name";s:5:"Alice";} -
array_unique对这些字符串去重,天然支持 -
array_map('unserialize', ...)恢复成原始结构,键名和类型都保留 - 注意:如果子数组含资源、闭包或某些不可序列化对象,
serialize()会失败,得提前过滤
按指定字段去重(比如只看 'email' 或 'id')
当你要的是“按某字段唯一”,而不是“整个子数组完全一致”时,serialize 就过度了。这时用 array_filter + $seen 哈希表更精准、更快。
示例(去重邮箱,忽略大小写):
$users = [['email'=>'[email protected]'], ['email'=>'[email protected]'], ['email'=>'[email protected]']];$seen = [];$unique = array_filter($users, function($u) use (&$seen) { $key = strtolower($u['email']); if (isset($seen[$key])) return false; $seen[$key] = true; return true;});
- 必须用
&$seen引用传递,否则每次回调都是空数组 - 用
isset($seen[$key])而不是in_array($key, $seen),避免 O(n) 查找拖慢大数组 - 若需连续数字索引,最后加
array_values($unique) - 字段不存在时会触发 Notice,建议先用
isset($u['email'])或array_key_exists防御
大数据量时性能差异明显
10 万条记录下,serialize + array_unique 比手写 foreach + isset 慢 2–3 倍——前者要三次完整遍历(serialize、unique、unserialize),后者一次搞定。
- 纯数值/字符串 ID 去重,直接用:
$seen = []; $result = []; foreach ($arr as $item) { if (!isset($seen[$item['id']])) { $seen[$item['id']] = true; $result[] = $item; } } - 字段值可能为
null或布尔型?不能直接当数组键,改用$key = serialize($item['field']) - 从数据库查出来的数据,常带字符串数字(如
'1'和1),array_unique默认松散比较会误判,手写逻辑可统一转类型再比
真正麻烦的从来不是怎么写,而是你是否意识到:array_unique 的“失效”,往往是因为你传给它的根本就不是它能处理的东西。
相关文章
- 苍蓝前线格奈森瑙强度如何-苍蓝前线格奈森瑙强度怎样 07-20
- 出发吧麦芬学者风暴之主养成攻略 07-20
- 英雄冒险团全部传家宝获取方法汇总 07-20
- 王者万象棋新手入门指引 王者万象棋零基础快速上手教程 07-20
- 检疫区最后一站金色收集品怎么获得 隐藏收集品获得方法介绍 07-20
- 息风谷战略牡丹如何获得 息风谷战略牡丹招募与获取方法详解 07-20