js数组去重方法分析与总结
数组去重经常被人拿来说事,虽然在工作中不常用,但他能够很好的考察js基础知识掌握的深度和广度,下面从js的不同阶段总结一下去重的方法。
ES3阶段
该阶段主要通过循环遍历数组从而达到去重的目的
- 多次循环去掉重复元素
// 以下所有方法默认都那拿该数组进行测试
var array = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN,{},{},[],[],{name: 'eric',sex: 'male'},{sex: 'male',name: 'eric'}];
function unique_es3_on2 (arr) {
var len = arr.length,
i = 0,
j,
flag,
ret = [];
for (; i < len ; i++) {
flag = true;
for (j = i+1 ; j < len ; j++) {
if (arr[i] === arr[j]) {
flag = false;
break;
}
}
if(flag) {
ret.push(arr[i]);
}
}
return ret;
}
unique_es3_on2(array)
结果如下图:
可见除了NaN没有去掉,其他效果都还挺好。原因就是NaN===NaN的结果是false。还有就是使用嵌套的循环,时间复杂度高,性能不是很好。
- 借助新的对象单次循环去掉重复元素
function unique_es3_on(arr) {
var obj = {},
i,
len = arr.length,
ret = [];
for(i = 0; i < len ; i++) {
if(!obj[arr[i]]) {
obj[arr[i]] = true;
ret.push(arr[i]);
}
}
return ret;
}
结果如下图:
虽然时间复杂度不高了,但是效果并不好。因为对象的属性是字符串,所以会把数组所有元素默认转化为字符串,就会产生以下问题:
- 数值1和字符串'1'以及包装类型new String('1'),转化为字符串以后是相同的会被去掉。
- 对象转化为字符串以后会被误判,[]>'',{}>'[object Object]',还有就是形式相同,内存地址不同的对象会被去除。
为了解决类型转换以后出现的问题,可以用typeof操作符转一下:
function unique_es3_on(arr) {
var obj = {},
i,
len = arr.length,
str,
ret = [];
for(i = 0; i < len ; i++) {
str = typeof arr[i] + arr[i];
if(!obj[str]) {
obj[str] = true;
ret.push(arr[i]);
}
}
return ret;
}
结果如图:
可以看到类型转换的问题基本解决,但对象部分基本都被去除了,因为他们和字符串相加时还是会发生转化,解决的方案是把上面的str换成str = typeof arr[i] + JSON.stringify(arr[i])
,相加之前先简单序列化一下。
结果如图:
从以上可以看出该阶段的各种方法或多或少的都有一些问题,该去除的没去掉,比如NaN。不该去的给去掉了,比如,形式相同但内存地址不同的对象(是否应该去掉全看你怎么定义)。
ES5阶段
function unique_es5(arr) {
return arr.filter(function(ele,index,array) {
return array.indexOf(ele) == index;
})
}
结果如图:
可以看到除了NaN,其他表现都是正常的。其中indexOf对于NaN总是返回-1,所以导致误判。
ES6阶段
let unique_includes = (arr) => {
let newArr = [];
arr.forEach(function(item){
if(!newArr.includes(item)){
newArr.push(item);
}
});
return newArr;
}
结果如图:
可以看到结果是符合预期的,es6中数组的扩展方法includes解决了用indexOf的弊端(不够直观,结果还要和索引进行比较。对NaN的误判)。
let unique_set = (arr) => {
return [...new Set(arr)];
}
结果和includes方法一样,此处利用es6新增数据结构set的特性,达到去重的目的。
let unique_map = (arr) => {
let ret = [],
m = new Map();
for(val of arr) {
if(!m.get(val)) {
m.set(val , true);
ret.push(val);
}
}
return ret;
}
结果和includes一样:
此处利用es6新增数据结构map的特性,之前的键值对集合(js对象),只能用字符串当作健,map这种数据结构打破了这一限制,各种类型的值都可以当作健,而且map的健是跟内存地址绑定的,只要内存地址不同就认为是不同的健,解决了之前形式相同而内存地址不同被去掉的问题。对于简单数据类型,只要严格相等就认为是相同的健,特例NaN也认为是相同的健。所以就解决了之前的两个大难题。
总结
虽然只是一个简单的去重问题,但这一路实践下来,可以看到js越来越强大,功能也越来越完善,同时也越来越优雅。
js数组去重方法分析与总结的更多相关文章
- js 数组去重方法汇总
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...
- 原声js数组去重方法
数组去重方法 方法一 ---- 利用数组filter + indexOf方法去重 方法二 ---- 利用数组forEach + indexOf方法去重 方法三 ---- 利用数组from方法 + Se ...
- Js数组去重方法总结
//方法一 var arr = [1,23,1,1,1,3,23,5,6,7,9,9,8,5]; function removeDuplicatedItem(arr) { for(var i = 0; ...
- 三种常用的js数组去重方法
第一种是比较常规的方法 思路: 1.构建一个新的数组存放结果 2.for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比 3.若结果数组中没有该元素,则存到结果数组中 Array.pro ...
- js数组去重方法包括Es6(方法有很多,但是需要考虑兼容性和数据类型场景)
1.Es6提供的方法 <script type="text/javascript"> //ES6里新添加了两个方法,set(set是一种新的数据结构,它可以接收一个数组 ...
- js 数组去重方法总结
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, ...
- js数组去重方法整理
1.思路:定义一个新数组,并存放原数组的第一个元素,然后将原数组的项和新数组的元素一一对比,若不同则存放在新数组中. function unique(arr){ var res = [arr[0]]; ...
- js数组去重方法集合
//第一种方法,新建一个空数组,将原来的数组循环逐个与新数组的成员做比较,如果新数组没有该元素就push进来 var arr = ['a', 1, 1, 1, 2, 4, 4, 'b', 'c', ' ...
- js 数组去重方法
var arr = ['a',1,2,3,'a',4,2,3,1,4,2,8,10,null,'a']; // 方法一 var newArr = [...new Set(arr)]; console. ...
随机推荐
- 利用 Traceview 精准定位启动时间测试的异常方法 (工具开源)
机智的防爬虫标识原创博客地址:http://www.cnblogs.com/alexkn/p/7095855.html博客求关注: http://www.cnblogs.com/alexkn 1.启动 ...
- CSS学习笔记10 相对定位,绝对定位与固定定位
文档流中的元素的位置由元素在 (X)HTML 中的位置决定,这就是最原始的普通流,前面讲到的浮动CSS学习笔记08 浮动可以改变元素在文档流中的位置,除了这个我们还可以通过使用CSS的position ...
- EXT 基础环境搭建
EXT 基础环境搭建使用 Sencha CMD 下载地址 https://www.sencha.com/products/extjs/cmd-download/ Sencha CMD 常用命令 API ...
- 【原】Sql Server 2008---安装时卸载Visual Studio
由于数据库连接不上,所以卸载数据库,然后安装的时候出问题报错,结果是因为vs, 所以就有了卸载vs这一步.某些图片借用一下. 1. 打开电脑中的控制面板--程序和功能 2.找到要卸载的软件,但是卸载过 ...
- 从源码的角度看Activity是如何启动的
欢迎访问我的个人博客,原文链接:http://wensibo.top/2017/07/03/Binder/ ,未经允许不得转载! 大家好,今天想与大家一起分享的是Activity.我们平时接触的最多的 ...
- 用py2exe将python文件转换成exe可执行程序
1.首先需要安装py2exe模块,下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 然后用pip install 命令安装py2exe模块,如果你用的py ...
- day4作业小代码练习
登录模块: 我们无论上那个网站,经常遇到这样的情况,让我们登录这个网站,流程图如下: 思路: 1.当我们登录网站的时候,我们首先会输入用户名,这个时候,有些网站会提醒我们用户名是否存在,如果我们输入的 ...
- 合格的IT人士需要养成的习惯:设置系统还原点
系统还原可帮助您将计算机的系统文件及时还原到早期的还原点.此方法可以在不影响个人文件(比如电子邮件.文档.照片等)的情况下,撤销对计算机的系统更改.有时,安装一个程序或驱动程序会导致对计算机的异常更改 ...
- 008.Adding a model to an ASP.NET Core MVC app --【在 asp.net core mvc 中添加一个model (模型)】
Adding a model to an ASP.NET Core MVC app在 asp.net core mvc 中添加一个model (模型)2017-3-30 8 分钟阅读时长 本文内容1. ...
- Oozie时bin/oozied.sh start或bin/oozied.sh run出现Bootstrap进程无法启动,http://bigdatamaster:11000/oozie界面也无法打开?E0103: Could not load service classes, java.lang.ClassNotFoundException: Class org.apache.oozie.ser
不多说,直接上干货! 问题详情 [hadoop@bigdatamaster oozie--cdh5.5.4]$ bin/oozied.sh start Setting OOZIE_HOME: /hom ...