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 相关文章推荐
图片上传即时显示缩略图的js代码
May 27 Javascript
js获取url中指定参数值的示例代码
Dec 14 Javascript
jquery操作select方法汇总
Feb 05 Javascript
JavaScript识别网页关键字并进行描红的方法
Nov 09 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
Dec 23 Javascript
javascript深拷贝的原理与实现方法分析
Apr 10 Javascript
微信小程序仿朋友圈发布动态功能
Jul 15 Javascript
浅谈VUE-CLI脚手架热更新太慢的原因和解决方法
Sep 28 Javascript
vue 中基于html5 drag drap的拖放效果案例分析
Nov 01 Javascript
JS中的函数与对象的创建方式
May 12 Javascript
vue服务端渲染操作简单入门实例分析
Aug 28 Javascript
vue-cli+iview项目打包上线之后图标不显示问题及解决方法
Oct 16 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 base64编码后解码乱码的解决办法
2014/06/19 PHP
php分页函数完整实例代码
2014/09/22 PHP
基于jQuery的input输入框下拉提示层(自动邮箱后缀名)
2012/06/14 Javascript
javascript:void(0)使用探讨
2013/08/27 Javascript
全面介绍javascript实用技巧及单竖杠
2016/07/18 Javascript
jQuery插件EasyUI实现Layout框架页面中弹出窗体到最顶层效果(穿越iframe)
2016/08/05 Javascript
Angularjs过滤器实现动态搜索与排序功能示例
2017/12/13 Javascript
浅谈React Native Flexbox布局(小结)
2018/01/08 Javascript
vue awesome swiper异步加载数据出现的bug问题
2018/07/03 Javascript
详解vue服务端渲染浏览器端缓存(keep-alive)
2018/10/12 Javascript
Layui弹出层 加载 做编辑页面的方法
2019/09/16 Javascript
Vue 监听元素前后变化值实例
2020/07/29 Javascript
[01:23]2014DOTA2国际邀请赛 球迷无处不在Ti现场世界杯受关注
2014/07/10 DOTA
[57:18]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#3VP VS VG
2016/03/03 DOTA
python 获取et和excel的版本号
2009/04/09 Python
Python格式化压缩后的JS文件的方法
2015/03/05 Python
python写日志封装类实例
2015/06/28 Python
python爬取淘宝商品详情页数据
2018/02/23 Python
Python绘制正余弦函数图像的方法
2018/08/28 Python
在python Numpy中求向量和矩阵的范数实例
2019/08/26 Python
python列表插入append(), extend(), insert()用法详解
2019/09/14 Python
selenium+Chrome滑动验证码破解二(某某网站)
2019/12/17 Python
python使用gdal对shp读取,新建和更新的实例
2020/03/10 Python
Python 私有属性和私有方法应用场景分析
2020/06/19 Python
python 提高开发效率的5个小技巧
2020/10/19 Python
HTML5操作WebSQL数据库的实例代码
2017/08/26 HTML / CSS
英国在线照明超市:Castlegate Lights
2019/10/30 全球购物
西雅图电动自行车公司:Rad Power Bikes
2020/02/02 全球购物
大学学习生活感言
2014/01/18 职场文书
和谐家庭演讲稿
2014/05/24 职场文书
网球场地租赁协议范本
2014/10/07 职场文书
2014年党风建设工作总结
2014/11/19 职场文书
2014年反洗钱工作总结
2014/11/22 职场文书
感谢信范文大全
2015/01/23 职场文书
三八妇女节寄语
2015/02/27 职场文书
Python使用pandas导入xlsx格式的excel文件内容操作代码
2022/12/24 Python