javascript的set无法直接对嵌套数组去重,因比较的是引用而非值;需用json.stringify转字符串再set过滤,或用map保证顺序,复杂结构需自定义比较。

JavaScript 的 Set 本身不能直接对嵌套数组(如 [[1,2], [1,2], [3,4]])去重,因为数组是引用类型,Set 比较的是内存地址而非内容。要去重,得先把每个子数组转成可比较的唯一标识(比如字符串),再用 Set 过滤,最后还原为数组。
把子数组转成字符串再用 Set 去重
这是最常用、简洁的方法:对每个子数组调用 JSON.stringify() 或 join() 转成字符串,放进 Set,再转回数组。
- 适用场景:子数组元素都是基础类型(数字、字符串、布尔值),且顺序固定
-
推荐用
JSON.stringify:能处理null、嵌套对象等,但要注意键序(ES2015+ 保证对象键序,一般够用) -
用
join(',')更轻量,但不适用于含逗号或非字符串/数字的元素(比如[1, 'a,b']会误判)
示例:
const arr = [[1, 2], [1, 2], [3, 4], [2, 1]]; const unique = [...new Set(arr.map(JSON.stringify))].map(JSON.parse); // → [[1,2], [3,4], [2,1]]
用 Map + JSON.stringify 实现稳定去重
如果需要保留首次出现的顺序,且避免 JSON.stringify 在某些边界情况下的问题(如 undefined、函数会被忽略),可用 Map 手动控制。
- 原理:以字符串为 key,原数组为 value,重复 key 不覆盖,自然保留第一次
- 比纯 Set 多一步还原,但逻辑更清晰、可控性更强
示例:
const arr = [[1, 2], [1, 2], [3, 4]];
const map = new Map();
arr.forEach(item => {
const key = JSON.stringify(item);
if (!map.has(key)) map.set(key, item);
});
const unique = [...map.values()];
处理含对象或复杂结构的嵌套数组
若子项不是简单数组,而是含对象、日期、正则等(JSON.stringify 会丢失信息或出错),需自定义比较逻辑。
- 可写一个浅比较函数(只比一层),配合
filter+some实现去重 - 深比较开销大,不建议在大数据量时用;真有需求可引入
lodash.isEqual - 简单替代:给每个对象加唯一 id 字段,按 id 去重
浅比较去重示例:
const arr = [[{a:1}, {b:2}], [{a:1}, {b:2}], [{x:3}]];
const unique = arr.filter((curr, i) =>
i === arr.findIndex(item =>
item.length === curr.length &&
item.every((v, j) => JSON.stringify(v) === JSON.stringify(curr[j]))
)
);
注意点和常见坑
-
Set对[1,2]和[1,2]视为两个不同值 —— 因为它们是不同引用 -
JSON.stringify([1,2]) === JSON.stringify([1,2])是true,但JSON.stringify([1,2]) === JSON.stringify([2,1])是false(顺序敏感) - 空数组
[]、JSON.stringify([])是"[]",没问题;但[undefined]会变成[null],需留意 - 性能上,
JSON.stringify+Set在万级以内数据表现良好,超十万建议分批或换算法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











