网站首页 > 技术文章 正文
对象数组去重方法
基于对象唯一标识符去重
1. Map 结构 + 属性映射
const uniqueArr = Array.from(
new Map(arr.map(item => [item.id, item])).values()
);
特点:
- 高效且简洁
- 适用于对象有唯一标识符的场景(如 id)
- 保留最后一个出现的对象
2. reduce + find/some 判断
const uniqueArr = arr.reduce((acc, cur) => {
const exists = acc.some(item => item.id === cur.id);
return exists ? acc : [...acc, cur];
}, []);
特点:
- 灵活,支持复杂逻辑
- 性能较低(O(n^2))
- 可自定义判断条件
基于对象内容哈希去重
1. JSON.stringify 序列化比较
const uniqueArr = arr.filter((item, index) => {
const str = JSON.stringify(item);
return index === arr.findIndex(obj => JSON.stringify(obj) === str);
});
特点:
- 简单,无需唯一属性
- 仅适用于对象内容完全一致且顺序相同的场景
- 无法处理属性顺序变化或嵌套对象中的引用差异
2. 自定义哈希函数
const hash = obj => `${obj.id}-${obj.name}`;
const uniqueArr = arr.filter((item, index) =>
index === arr.findIndex(obj => hash(obj) === hash(item))
);
特点:
- 高度灵活,支持复杂对象结构
- 需手动维护哈希逻辑
- 可根据业务需求定制哈希规则
普通值数组去重方法
ES6+ 高效方法
1. Set 数据结构
const uniqueArr = [...new Set(arr)];
// 或
const uniqueArr = Array.from(new Set(arr));
特点:
- 代码简洁
- 时间复杂度为 O(n)
- 自动处理 NaN(认为 NaN === NaN)
2. Map 数据结构
const map = new Map();
arr.forEach(item => map.set(item, true));
const uniqueArr = Array.from(map.keys());
特点:
- 适用于复杂场景
- 性能与 Set 相近
- 可保留特定顺序
ES5 兼容方法
1. filter + indexOf
const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index);
特点:
- 兼容性好
- 无法识别 NaN(两个 NaN 会被视为不重复)
- 性能中等
2. reduce 累加
const uniqueArr = arr.reduce((acc, cur) =>
acc.includes(cur) ? acc : [...acc, cur], []);
特点:
- 逻辑清晰
- 时间复杂度为 O(n^2)
- 支持链式调用
3. 对象键值对法
const obj = {};
const uniqueArr = [];
arr.forEach(item => {
if (!obj[item]) {
obj[item] = true;
uniqueArr.push(item);
}
});
特点:
- 性能较高(O(n))
- 会将 1 和 "1" 视为相同
- 不适用于复杂数据类型
方法对比与选择建议
对象数组去重
方法 | 适用场景 | 优点 | 缺点 |
Map + 唯一标识符 | 对象有明确唯一属性 | 高效、代码简洁 | 依赖唯一属性 |
reduce + find/some | 无唯一属性但需动态判断 | 灵活 | 性能较低 |
JSON.stringify | 对象内容完全一致 | 简单 | 不适用动态属性 |
自定义哈希函数 | 需要自定义规则 | 高度灵活 | 需维护哈希逻辑 |
普通值数组去重
方法 | 适用场景 | 优点 | 缺点 |
Set | ES6+ 环境 | 高效(O(n)) | 无法区分 NaN |
filter + indexOf | 兼容旧浏览器 | 无需依赖 ES6 | 无法处理 NaN |
对象键值对法 | 高性能需求 | O(n) | 混淆类型 |
reduce | 逻辑清晰 | 支持链式调用 | 性能较低 |
示例场景
对象数组去重
// 用户列表去重(基于 userId)
const users = [
{ userId: 1, name: 'Alice' },
{ userId: 2, name: 'Bob' },
{ userId: 1, name: 'Alice' } // 重复项
];
const uniqueUsers = Array.from(new Map(users.map(u => [u.userId, u])).values());
普通值数组去重
// 处理包含 NaN 的数组
const arr = [NaN, 1, NaN, 2];
const uniqueArr = Array.from(new Set(arr)); // [NaN, 1, 2]
注意事项
- 对象去重需根据业务需求选择策略,优先使用 Map 或唯一属性法提升性能
- 对于复杂场景,可结合哈希函数或工具库(如 lodash.uniqBy)简化实现
- 普通值去重中,Set 方法在 ES6+ 环境下是最优选择
- 兼容旧浏览器时,filter + indexOf 或对象键值对法是较好选择
- 注意不同类型值的处理(如数字 1 和字符串 "1")
- NaN 的处理在不同方法中表现不同,需特别注意
猜你喜欢
- 2025-05-05 28.ECMAScript 标准深度解析(何为ecmascript)
- 2025-05-05 Vite 性能篇:掌握这些优化策略,一起纵享丝滑!
- 2025-05-05 前端常见20道高频面试题深入解析(前端面试题目100及最佳答案)
- 2025-05-05 2025 年 Object 和 Map 如何选择?
- 2025-05-05 学习ES6- 入门Vue(大量源代码及笔记,带你起飞)
- 2025-05-05 JavaScript去除数组重复元素的几种方法
- 2025-05-05 AI 自我升级神操作,难道真要开启 “天网” 序章?
- 2025-05-05 20 个让人惊叹的 JavaScript 单行代码技巧,效率瞬间提升
- 2025-05-05 ES6新特性面试题及答案(es6 面试)
- 2025-05-05 为什么前端开发者都用Set代替Array去重?实测性能对比
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- js判断是否空对象 (63)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- phprequire_once (61)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)