当前位置: 首页 > news >正文

JavaScript 数组去重:11 种方法对比与实战指南

文章目录

    • 前言
    • 一、使用 `Set` 数据结构
    • 二、使用 `filter` + `indexOf`
    • 三、使用 `reduce` 累加器
    • 四、双重 `for` 循环
    • 五、利用对象属性唯一性
    • 六、先排序后去重
    • 七、使用 `Map` 数据结构
    • 八、使用 `includes` 方法
    • 九、优化处理 `NaN` 的 `filter` 方法
    • 十、利用 `findIndex`
    • 十一.利用`Set`和展开运算符处理多维数组
    • 总结

前言

一、使用 Set 数据结构

function uniqueBySet(arr){return [...new Set(arr)]
}

利用 Set 数据结构中重复元素会被自动过滤的特点。

  • 优点:简单高效,时间复杂度为 O(n)。
  • 注意:无法区分对象引用类型,但是可以处理 NaN

二、使用 filter + indexOf

function uniqueByFilter(arr){return arr.filter((item,index)=> arr.indexOf(item) === index)
}

使用 indexOf 返回元素首次出现的索引,若非当前索引则过滤。

  • 注意:时间复杂度为 O(n²),不处理 NaN,因为 indexOf(NaN) 始终返回 -1。

三、使用 reduce 累加器

function uniqueByReduce(arr) {return arr.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
}

使用 reduce 检查当前元素是否存在于累加数组中,存在则不添加,不存在则添加。

  • 注意:时间复杂度为 O(n²),空间复杂度较高。

四、双重 for 循环

function uniqueByLoop(arr) {const result = [];for (let i = 0; i < arr.length; i++) {let isDuplicate = false;for (let j = 0; j < result.length; j++) {if (arr[i] === result[j]) {isDuplicate = true;break;}}if (!isDuplicate) result.push(arr[i]);}return result;
}

通过循环嵌套比较元素是否重复。

  • 注意:时间复杂度为 O(n²),性能较差。

五、利用对象属性唯一性

function uniqueByObj(arr){const obj = {}return arr.filter(item=>{const key = typeof item + JSON.stringify(item)return obj.hasOwnProperty(key) ? false :(obj[key] = true) })

对象的键名唯一,通过序列化来区分不同类型及对象。

  • 注意JSON.stringify 无法处理函数、循环引用,性能一般。

六、先排序后去重

function uniqueBySort(arr) {const sortedArr = [...arr].sort();return sortedArr.filter((item, index) => index === 0 || item !== sortedArr[index - 1]);
}

对数组排序后,重复的元素会相邻,然后直接过滤。

  • 注意:原数组顺序会被改变。

七、使用 Map 数据结构

function uniqueByMap(arr){const map = new Map()return arr.filter(item=>!map.has(item) && map.set(item,true))
}

利用 Map 键的唯一性可以快速判断元素是否存在。

  • 优点:时间复杂度为 O(n),可以正确处理对象引用和 NaN

八、使用 includes 方法

function uniqueByIncludes(arr) {const result = [];for (const item of arr) {if (!result.includes(item)) result.push(item);}return result;
}

在遍历时检查元素是否已存在于结果数组。

  • 注意:时间复杂度为 O(n²),不能处理 NaN

九、优化处理 NaNfilter 方法

function uniqueWithNaN(arr) {const hasNaN = arr.some(item => Number.isNaN(item));const result = arr.filter((item, index) => {if (Number.isNaN(item)) {// 仅保留第一个NaNreturn !hasNaN || (index === arr.findIndex(i => Number.isNaN(i)));}return arr.indexOf(item) === index;});return result;
}

单独处理 NaN,确保只保留第一个出现的 NaN

  • 优点:该方法兼容 NaN 去重。

十、利用 findIndex

function uniqueByFindIndex(arr) {return arr.filter((item, index) => {return arr.findIndex(i => i === item) === index;});
}

使用 findIndexindexOf 方法类似,但是可以处理自定义处理 NaN

十一.利用Set和展开运算符处理多维数组

function uniqueMultidimensionalArray(arr) {return Array.from(new Set(arr.flat(Infinity)));
}

首先利用flat方法将多维数组扁平化,然后利用Set去除重复元素,最后通过Array.fromSet转换会数组

  • 注意:该方法只能处理元素为基本类型或可序列化的对象的多维数组。如果数组中包含函数,循环引用等特殊对象,flat方法和Set可能无法正确处理

总结

  • 简单场景:优先使用 SetMap,简洁高效。
  • 兼容性要求:使用 filter + indexOf 或者双重循环。
  • NaN 或者对象:选择 Map 或改进的对象属性方法。
  • 排序无影响:排序后去重效率高 。

相关文章:

  • 每天五分钟机器学习:KTT条件
  • QMK自定义4*4键盘固件创建教程:最新架构详解
  • HTTP 的发展史:从前端视角看网络协议的演进
  • Spring 必会之微服务篇(2)
  • Unity Shaders and Effets Cookbook
  • 汽车四缸汽油机曲柄连杆机构设计关键技术研究
  • 测试左移系列-产品经理实战-实战认知1
  • SpringCloud之Gateway基础认识-服务网关
  • 搜索与图论
  • 用java+vert.x开发的内网穿透工具jrp-nat
  • MySQL 从入门到精通(三):日志管理详解 —— 从排错到恢复的核心利器
  • 互联网大厂Java求职面试:AI集成场景下的技术挑战与架构设计
  • 进程间通信--管道【Linux操作系统】
  • Docker、Docker-compose、K8s、Docker swarm之间的区别
  • Linux基本指令(一)
  • LeetCode LCR 007. 三数之和 (Java)
  • 服饰行业的转型“助推器”来了
  • 基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
  • 8.3.监控与日志体系
  • Helix:一种用于通用人形控制的视觉语言行动模型
  • 观察|天空之外的战场:官方叙事、新闻与社交平台中的印巴冲突
  • 咸宁市委常委、市纪委书记官书云调任湖北省司法厅副厅长
  • 专访|高圆圆:像鸟儿一样,柔弱也自由
  • 美政府被曝下令加强对格陵兰岛间谍活动,丹麦将召见美代办
  • 印对巴军事打击后,巴外交部召见印度驻巴临时代办
  • 宁合两大都市圈交汇之城含山:要想身体好,常往含山跑