JS数组去重详情


Posted in Javascript onNovember 07, 2021

1 测试用例

// 测试用例
const a = {};
const b = { c: 1 };
const array = [
  1, 1, "1", "1",
  {}, {}, { c: 1 }, { c: 1},
  a, a, b, b, 
  [], [], [1], [1],
  undefined, undefined,
  null, null,
  NaN, NaN,
];

2 JS 数组去重4大类型

2.1 元素比较型

此类型通过数组元素之间进行比较来去重

2.1.1 双层 for 循环逐一比较(es5常用)

使用双层for循环逐一比较数组元素,用splice方法去除重复的元素

// 双层for循环
function uniq1(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = i + 1; j < arr.length; j++) {
            if (arr[i] === arr[j]) {
                arr.splice(j, 1)
                j--
            }
        }
    }
    return arr
}

// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]

通过对比去重前后结果,重复的NaN没有去掉,因为NaN === NaNfalse

2.1.2 排序相邻比较

使用sort()方法对数组元素进行排序,然后比较相邻元素,用splice方法去除重复的元素。

function uni2(arr) {
    arr.sort();
    for (let i = 0; i < arr.length - 1; i++) {
        arr[i] === arr[i + 1] && arr.splice(i + 1, 1) && i--;
    }
    return arr;
}

也可以创建新数组,将不重复的元素放入新数组中

function uniq3(arr) {
    arr = arr.sort()
    const newArr = [arr[0]]
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i - 1]) {
            newArr.push(arr[i])
        }
    }
    return newArr
}

// 去重结果
// [[],[],1,'1',[1],[1],NaN,NaN,{},{},{c:1},{c:1},{},{c:1},null,undefined]

重复的NaN没有去掉,因为NaN === NaN为false
sort
默认排序顺序是将元素转换为字符串,对象转换为字符串都是[object Object] ,所以sort方法不能对数组中的对象进行排序,也就有可能无法去除重复的对象,除非重复的对象本就相邻

2.2 查找元素位置型

此类型通过查找元素第一次出现的位置来去重

2.2.1 indexOf

通过indexOf查找当前元素第一次出现的位置是否为当前位置,若是,则放入新数组

function uniq4(arr) {
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (arr.indexOf(arr[i]) === i) {
            res.push(arr[i])
        }
    }
    return res
}

// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]

同样,因为NaN === NaNfalse,所以用indexOf查找NaN结果总是-1,从而在新数组中不会有NaN

2.2.2 findIndex

通过findIndex查找当前元素第一次出现的位置是否为当前位置,若是,则放入新数组

function uniq5(arr) {
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (arr.findIndex(item => item === arr[i]) === i) {
            res.push(arr[i])
        }
    }
    return res
}
// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]

同样,因为NaN === NaNfalse,所以用findIndex查找NaN结果总是-1,从而在新数组中不会有NaN

2.3 元素是否存在型

此类型通过判断在新数组中是否存在当前元素来去重

2.3.1 includes

includes方法用来判断一个数组是否包含一个指定的值

function uniq6(arr) {
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (!res.includes(arr[i])) {
            res.push(arr[i])
        }
    }
    return res
}
// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]

includes使用零值相等算法来确定是否找到给定的元素,所以可以判断NaN是否在新数组中存在

2.3.2 some

some方法用来测试数组中是否至少有1个元素通过了被提供的函数测试

function uniq7(arr) {
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (!res.some(item => item === arr[i])) {
            res.push(arr[i])
        }
    }
    return res
}
// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]

同样,这里仍旧使用了===来比较元素,因为NaN === NaNfalse,所以新数组中会有多个NaN

2.4 依托数据结构特性

此类型通过ES6提供的数据结构MapSet本身不可重复特性来去重

2.4.1 Map

ES6提供的Map结构可以用各种类型的值(包括对象)当作键,且键是唯一的

function uniq8(arr) {
    const map = new Map()
    for (let i = 0; i < arr.length; i++) {
        !map.has(arr[i]) && map.set(arr[i], true)
    }
    return [...map.keys()]
}
// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]

map.has方法对NaN也有效

2.4.2 Set(ES6 最常用)

Set结构的成员的值都是唯一的,没有重复的值。

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

// 去重结果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]

3 补充

上面所说的方法可以使用不同的Api进行改动,比如使用splice方法去除数组元素的地方,我们可以通过filter方法来过滤数组得到新数组;

再比如includes的方法中不用for循环遍历数组,通过reduce方法来代替等等。

总之,方法有很多,但是万变不离其宗

有些去重方法对NaN无效,因为NaN === NaNfalse,如果有需求,可以使用Object.is(NaN, NaN)true来进行修改

实际应用中,最常用的方法就是使用Set,也可以使用第三方库lodash来处理

到此这篇关于JS数组去重详情的文章就介绍到这了,更多相关JS数组去重内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript网页关键字高亮代码
Jul 30 Javascript
Mootools 1.2教程 滚动条(Slider)
Sep 15 Javascript
jQuery 白痴级入门教程
Nov 11 Javascript
利用js 进行输入框自动匹配字符的小例子
Jun 29 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 图片库
Jan 09 Javascript
JavaScript日期时间与时间戳的转换函数分享
Jan 31 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
Jan 19 Javascript
浅谈Vue.js
Mar 02 Javascript
js获取一组日期中最近连续的天数
May 25 Javascript
IE11下使用canvas.toDataURL报SecurityError错误的解决方法
Nov 19 Javascript
Vue下拉框回显并默认选中随机问题
Sep 06 Javascript
关于引入vue.js 文件的知识点总结
Jan 28 Javascript
手写实现JS中的new
Nov 07 #Javascript
用JS写一个发布订阅模式
Nov 07 #Javascript
浅谈JavaScript浅拷贝和深拷贝
JavaScript严格模式不支持八进制的问题讲解
Javascript使用integrity属性进行安全验证
Nov 07 #Javascript
JavaScript中时间格式化新思路toLocaleString()
Nov 07 #Javascript
JavaScript中isPrototypeOf函数
You might like
PHP 5昨天隆重推出--PHP 5/Zend Engine 2.0新特性
2006/10/09 PHP
?繁体转换的class
2006/10/09 PHP
php 取得瑞年与平年的天数的代码
2009/08/10 PHP
PHP的基本常识小结
2013/07/05 PHP
详解使用php调用微信接口上传永久素材
2017/04/11 PHP
Laravel5中Cookie的使用详解
2017/05/03 PHP
如何做到打开一个页面,过几分钟自动转到另一页面
2007/04/20 Javascript
jQuery $.each的用法说明
2010/03/22 Javascript
关于javascript模块加载技术的一些思考
2014/11/28 Javascript
每天一篇javascript学习小结(RegExp对象)
2015/11/17 Javascript
AngularJS中的表单简单入门
2016/07/28 Javascript
jQuery 局部div刷新和全局刷新方法总结
2016/10/05 Javascript
Centos7 中安装 Node.js v4.4.4
2016/11/03 Javascript
js 获取html5的data属性实现方法
2017/07/28 Javascript
vue中使用cropperjs的方法
2018/03/01 Javascript
微信小程序云开发如何使用云函数生成二维码
2019/05/18 Javascript
Javascript查看大图功能代码实现
2020/05/07 Javascript
[00:35]TI7不朽珍藏III——寒冰飞龙不朽展示
2017/07/15 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
[44:33]EG vs Liquid 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
基于Python实现通过微信搜索功能查看谁把你删除了
2016/01/27 Python
Python tkinter模块弹出窗口及传值回到主窗口操作详解
2017/07/28 Python
新手常见6种的python报错及解决方法
2018/03/09 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
2018/07/16 Python
Python 串口读写的实现方法
2019/06/12 Python
PyQt5实现简易电子词典
2019/06/25 Python
django-crontab 定时执行任务方法的实现
2019/09/06 Python
python为Django项目上的每个应用程序创建不同的自定义404页面(最佳答案)
2020/03/09 Python
python使用gdal对shp读取,新建和更新的实例
2020/03/10 Python
Anaconda+vscode+pytorch环境搭建过程详解
2020/05/25 Python
Numpy中ndim、shape、dtype、astype的用法详解
2020/06/14 Python
房地产活动策划方案
2014/05/14 职场文书
学校安全生产承诺书
2014/05/23 职场文书
检讨书模板大全
2015/05/07 职场文书
2016年小学生新年寄语
2015/08/18 职场文书
golang elasticsearch Client的使用详解
2021/05/05 Golang