这么全的数组去重,你怕不怕?
以 var arr = [1,2,3,1]; 作为测试用例
方法一:双循环 (时间复杂度比较高,性能一般。)
A、(1)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var isRepeat;5 6 for(var i=0; i<len; i++) { //第一次循环7 isRepeat = false;8 for(var j=i+1; j<len; j++) { //第二次循环9 if(arr[i] === arr[j]){ 10 isRepeat = true; 11 break; 12 } 13 } 14 if(!isRepeat){ 15 newArr.push(arr[i]); 16 } 17 } 18 return newArr; 19 }
输出 newArr 结果:
B、(2)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 for(var i=0; i<len; i++){ // 第一次循环5 for(var j=i+1; j<len; j++){ // 第二次循环6 if(arr[i] === arr[j]){7 j = ++i;8 }9 } 10 newArr.push(arr[i]); 11 } 12 return newArr; 13 }
输出 newArr 结果:
tip: j = ++ i; 等价于 j = j+1; i = i+1;
整体思路就是 如果是重复元素,则跳过重复元素,不对其进行 push 操作。
方法二:Array.prototype.indexOf()
A、(3)
1 function unique(arr) { 2 return arr.filter(function(item, index){ //item 表示数组中的每个元素,index 是每个元素的出现位置。 3 return arr.indexOf(item) === index; // indexOf 返回第一个索引值 4 }); 5 }
输出 新 arr 结果:
tip:var new_arrary = arr.filter(callback[, thisArg]); 其中
callback 用来测试数组的每个元素的函数。调用时使用参数 element, index, array。
返回true表示保留该元素(通过测试),false则不保留。thisArg
可选,执行 callback
时的用于 this
的值。
整体思路就是
索引不是第一个索引,说明是重复值。
B、(4)
1 function unique(arr) { 2 var newArr = []; 3 arr.forEach(function(item){ //一次循环,item 即为数组中的每一项 4 if(newArr.indexOf(item) === -1){ 5 newArr.push(item); 6 } 7 }); 8 return newArr; 9 }
输出 newArr 结果:
方法三:Array.prototype.sort()
A、(5)
1 function unique(arr) {2 var newArr = []; 3 arr.sort();4 for(var i = 0; i < arr.length; i++){5 if( arr[i] !== arr[i+1]){6 newArr.push(arr[i]);7 }8 }9 return newArr; 10 }
输出 newArr 结果:
tip: 整体思路就是 先进行排序,然后比较相邻元素。
B、(6)
1 function unique(arr) {2 var newArr = []; 3 arr.sort();4 var newArr = [arr[0]];5 for(var i = 1; i < arr.length; i++){6 if(arr[i] !== newArr[newArr.length - 1]){7 newArr.push(arr[i]);8 }9 } 10 return newArr; 11 }
输出 newArr 结果:
tip:整体思路就是 先进行排序,将原数组中的第一个元素复制给结果数组,然后检查原数组中的第 i 个元素 与 结果数组中的最后一个元素是否相同。
方法四:使用对象key来去重 (7)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 for(var i=0; i<len; i++){6 if(!tmp[arr[i]]){7 tmp[arr[i]] = 1;8 newArr.push(arr[i]);9 } 10 } 11 return newArr; 12 }
输出 newArr 结果:
tip:整体思路就是 利用了对象(tmp)的 key 不可以重复的特性来进行去重。 但是会出现如下问题需要注意:
1、无法区分隐式类型转换成字符串后一样的值,比如 1 和 '1' 。
2、无法处理复杂数据类型,比如对象(因为对象作为key会变成[object Object])。
3、特殊数据,比如 '__proto__' 会挂掉,因为 tmp 对象的 __proto__ 属性无法被重写。
针对以上问题,解决办法有:
解决问题一、三:可以为对象的 key 增加一个类型,或者将类型放到对象的value中来解决:(8)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 var tmpKey;6 for(var i=0; i<len; i++){7 tmpKey = typeof arr[i] + arr[i];8 9 console.log(tmpKey); 10 11 if(!tmp[tmpKey]){ 12 tmp[tmpKey] = 1; 13 newArr.push(arr[i]); 14 } 15 } 16 return newArr; 17 }
输出 newArr 结果:
tip: 代码中第 9 行 console 出来的东西 如图:
解决问题二:可以将对象序列化之后作为key来使用。这里为简单起见,使用JSON.stringify()进行序列化。(9)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 var tmpKey;6 for(var i=0; i<len; i++){7 tmpKey = typeof arr[i] + JSON.stringify(arr[i]);8 9 console.log(tmpKey) 10 11 if(!tmp[tmpKey]){ 12 tmp[tmpKey] = 1; 13 newArr.push(arr[i]); 14 } 15 } 16 return newArr; 17 }
输出 newArr 结果:
tip: 代码中第 9 行 console 出来的东西 如图:
看起来和上面一种方法 console 的没有区别,但是将 测试用例 换成一个 对象 var arr = [{xiaoming:23,xiaoqing:45},{xiaoming:24,xiaoqing:45}]; 时,可以看到 console 结果如下:
以上都是一些比较普遍的解决办法,下面补充一下 es6 中的方法以及对于 null,NaN,undefined,{} 等类型的去重。
一、es6:
方法一: Map (10)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = new Map();5 for(var i=0; i<len; i++){6 if(!tmp.get(arr[i])){7 tmp.set(arr[i], 1);8 newArr.push(arr[i]);9 } 10 } 11 return newArr; 12 }
输出 newArr 结果:
tip: Map 是一种新的数据类型,类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。可以把它想象成key类型没有限制的对象。它的存取使用单独的get()、set()接口。
方法二:Set (11)
1 function unique(arr){ 2 var set = new Set(arr); 3 return Array.from(set); 4 }
输出 newArr 结果:
tip:Set 是一种新的数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。Array.from() 方法从类似数组或可迭代对象创建一个新的数组实例。
想要具体了解 Set 和 Map ,查看 http://wiki.jikexueyuan.com/project/es6/set-map.html
方法三:Array.prototype.includes() (12)
1 function unique(arr) { 2 var newArr = []; 3 arr.forEach(function(item){ 4 if(!newArr.includes(item)){ 5 newArr.push(item); 6 } 7 }); 8 return newArr; 9 }
输出 newArr 结果:
二、NaN 等类型数据的去重:
使用测试用例,对上面所有算法进行验证 (以 黄色数字 为测试顺序)
1 var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/] 2 3 console.log(unique(arr));
得到结果如下:
tips:
That's all ~
学习并感谢:
这么全的数组去重,你怕不怕?相关推荐
- 史上最全JavaScript数组去重的十种方法(推荐)
一.前言: 我们在实际工作中,或者在面试找工作时,都会用到或者被问到一个问题,那就是"数组如何去重".是的,这个问题有很多种解决方案,看看下面的十种方式吧! 二.数组去重方式大汇总 ...
- 超全的数组去重12种方法
前言 数组去重,可以说是一个比较常见的面试题,今天来盘点一下都有哪些方法可以实现数组去重. 方法1.双重for循环 这是一个最笨的方法,双重循环. var arr = [1, 2, 3,4 ,5,6, ...
- java数组去重_数组去重12种方案-你要的全在这
首先我们先温习一下数组的常用的方法 pop push shift unshift slice splice sort reverse concat join indexOf lastIndexOf m ...
- JS----JavaScript数组去重(12种方法,史上最全)
数组去重的方法 一.利用ES6 Set去重(ES6中最常用) Set 不包含重复元素的值的集合 Map 双列集合 键值对 与object的区别 : object中的key只能是string类型 而Ma ...
- 超全的12种数组去重的方法
前言 数组去重,可以说是一个比较常见的面试题,今天来盘点一下都有哪些方法可以实现数组去重. 方法1.双重for循环 这是一个最笨的方法,双重循环. var arr = [1, 2, 3,4 ,5,6, ...
- 啊这,一道数组去重的算法题把东哥整不会了…
学算法认准 labuladong 东哥带你手把手撕力扣???? 点击下方卡片即可搜索???? 想啥呢?labuladong 怎么可能被整不会?只是东哥又发现了一个有趣的套路,所以写了篇文章分享给大家~ ...
- 数组去重的正确编写姿势
引言 数组去重是前端面试的一个必备题目,其具体表现内容为:怎样去掉Javascript的Array的重复项.问题简单直接,咱们也废话不多说,直入主题吧. 一般姿势 使用数组的indexOf()方法可以 ...
- java数组去重_再谈JavaScript数组去重
JavaScript的数组去重是一个老生常谈的话题了.随便搜一搜就能找到非常多不同版本的解法. 细想一下,这样一个看似简单的需求,如果要做到完备,涉及的知识和需要注意的地方着实不少. 定义重复(相等) ...
- javascript小实例,多种方法实现数组去重问题
废话不多说,直接拿干货! 先说说这个实例的要求:写一个方法实现数组的去重.(要求:执行方法,传递一个数组,返回去重后的新数组,原数组不变,实现过程中只能用一层循环,双层嵌套循环也可写,只做参考): 先 ...
最新文章
- 东八区转为0时区_踩坑记 | Flink 天级别窗口中存在的时区问题
- MySQL Percona PXC集群实现MySQL主从复制强一致性
- Nginx添加SSL的支持
- python如何导入自定义模块_【python】导入自定义模块
- H5实现拍照及相册图片上传
- 为转型绞尽脑汁,新东方到美国教中文!网友:卷到国外去了
- 通过CocoCut插件和m3u8下载器下载网页视频并转换成mp4格式
- 2019~2020数字货币领域发展趋势报告
- ​李宏毅机器学习——领域适应Domain Adaptation
- Spark Streaming背压机制
- sql计算上班总时长——以每天的第一次上下班打卡时间为准
- 联发科希望P40和P70救命,能如愿么?
- 通过公网+域名访问家里的群晖服务器
- 拦截图片代码 精易web浏览器_[原创]用Com HOOK实现拦截WebBrowser的alert函数调用
- pppoe服务器稳定性,架设pppoe服务器 实现欺骗的防御(3)
- POI 操作Excel的单元格样式超过64000的异常问题解决
- volatile c 关键字
- 时间的格式-用字符表示
- 认识计算机网络参考模型
- Python快速教程 - 基础篇