javascript递归深度去重多维数组需分层处理:先对当前层元素判重,再递归处理子数组;用json.stringify标准化键值,set记录已见项,保持嵌套结构。

JavaScript 中用递归深度去重多维嵌套数组,核心是把“去重”和“递归遍历”拆开处理:先对当前层级做唯一性判断,再对子数组递归调用同一逻辑。关键在于如何定义“重复”——原始值可直接比较,而数组或对象需标准化(如 JSON.stringify)后比对。
基础思路:扁平化 + Set 判重不适用,必须逐层递归
不能直接用 JSON.stringify 一次性序列化整个多维数组再去重,因为那样会丢失结构(比如 [[1,2],[1,2]] 变成两个相同字符串,但你想要的是保留一个子数组,而不是合并成一维)。正确做法是:对每个元素单独处理——如果是数组,就递归去重;如果不是,就按值判重。
- 用
Set或Map存已见的“标准化键”,避免重复添加 - 对数组元素调用自身函数,实现深度穿透
- 对非数组项(数字、字符串等),用
JSON.stringify(item)作键更稳妥(能区分0和false等)
标准实现:支持任意嵌套层级
下面是一个稳定可用的递归函数,它对每个元素做标准化处理后查重,并保持原结构:
function deepUnique(arr) {
const seen = new Set();
return arr.filter(item => {
// 对数组递归处理,再序列化;对原始值直接序列化
const key = Array.isArray(item)
? JSON.stringify(deepUnique(item))
: JSON.stringify(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
使用示例:
const data = [[1, 2], [3, 4], [1, 2], [5, [6, 7]], [5, [6, 7]]]; console.log(deepUnique(data)); // 输出: [[1, 2], [3, 4], [5, [6, 7]]]
注意:该方法依赖 JSON.stringify,所以无法区分 undefined、function、Symbol 和循环引用,也不处理 NaN(会被转为 null)。如需支持这些,需自定义序列化逻辑。
进阶:支持自定义比较与特殊值处理
若需识别 NaN、保留 undefined、或按对象字段去重(如 {id: 1}),可传入比较函数替代 JSON.stringify:
- 把
seen改为Map,键为自定义生成的唯一标识 - 对每个
item调用getCompareKey(item),返回字符串或 symbol - 例如:
getCompareKey = x => Array.isArray(x) ? `arr_${deepUnique(x).length}` : `${x}`(示意,实际按需定制)
注意事项与性能提醒
递归深度去重虽逻辑清晰,但有现实约束:
- 大数组易触发栈溢出(尤其 Chrome 默认约 10k 层),建议加递归深度限制或改用栈模拟
- 每次
JSON.stringify开销较大,嵌套深、元素多时明显变慢 - 无法还原原始引用关系(所有数组都会被新创建),不适合需保留对象身份的场景
- 空数组
[]和空对象{}在 JSON 中都变成[]和{},可区分;但new Date()、RegExp会被转为空对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











