数组去重涉及基础知识较多,总结了以下6个方法:
-
双重for循环,push新数组;
-
双重for循环,splice原数组;
-
单个for循环,遍历对象属性;
-
单个for循环,sort排序后遍历;
-
ES5,indexOf,定位去重;
-
ES6,... 及set方法。
1、双层循环,若有相同的值则跳过,不相同则push进新数组
1 Array.prototype.distinct1 = function(){ 2 var arr = this, 3 i,j, 4 len = arr.length, 5 result = []; 6 7 for (i = 0; i < len; i++){ 8 for (j = i + 1; j < len; j++ ){ 9 if(arr[i] === arr[j]){ //判断有相等项 10 j = ++i; // 执行跳出内循环 i = i+1; j=i; 11 } 12 } 13 result.push(arr[i]); 14 } 15 return result; 16 }; 17 var arr1 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 18 console.log(arr1.distinct1()) //返回 [1, "1", true, "true"]
2、双层循环,原数组上进行删除操作(splice)
1 Array.prototype.distinct2 = function () { 2 var arr = this, 3 i, 4 j, 5 len = arr.length; 6 for(i = 0; i < len; i++){ 7 for(j = i + 1; j < len; j++){ 8 if (arr[i] === arr[j]){ 9 arr.splice(j,1); //判断后将其移除 10 len--; //原数组长度减1 11 j--; //内部循环索引减1 12 } 13 } 14 } 15 return arr; 16 }; 17 var arr2 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 18 console.log(arr2.distinct2()); //[1, "1", true, "true"]
3、对象属性,利用对象属性名称不能相同,遍历数组,利用obj对象保存数组值
1 // 判断数组值是否已经保存在obj中,未保存则push到新数组并用obj[arr[i]]=1记录保存 2 Array.prototype.distinct3 = function (){ 3 var arr = this, 4 i, 5 result = [], 6 obj = {}, 7 len = arr.length; 8 for(i = 0; i < len; i++){ 9 if(!obj[arr[i]]){ //若obj[arr[i]] == false,即obj中查找不到arr[i]属性 10 obj[arr[i]] = 1; //对象属性赋值 11 result.push(arr[i]); 12 } 13 } 14 return result; 15 }; 16 17 var arr3 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 18 console.log(arr3.distinct3()); //[1, true] ,对象属性默认调用toString()方法,需要优化
4、sort(),将数组进行排序,再调用一次for循环
1 Array.prototype.distinct4 = function (){ 2 var arr = this, 3 i, 4 len = arr.length; 5 arr.sort(); //对传入数组排序 6 var nArr = [arr[0]]; //用arr[0]初始化新数组 7 for (i = 0; i < len; i++){ 8 if(arr[i] !== nArr[nArr.length - 1]){ //与新数组从最后一项向前对比 9 nArr.push(arr[i]); 10 } 11 } 12 return nArr; 13 }; 14 var arr4 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 15 console.log(arr4.distinct4()); //[1, "1", true, "true"]
5、indexOf() 定位查找
兼容IE8 indexOf() 方法
1 Array.prototype.forEach = Array.prototype.forEach || function(callback, thisArg) { 2 if (!callback || typeof callback !== ‘function‘) return; 3 4 for (var i = 0, j = this.length; i < j; i++) { 5 callback.call(thisArg, this[i], i, this); 6 } 7 }
兼容IE8 forEach() 方法
1 Array.prototype.forEach = Array.prototype.forEach || function(callback, thisArg) { 2 if (!callback || typeof callback !== ‘function‘) return; 3 4 for (var i = 0, j = this.length; i < j; i++) { 5 callback.call(thisArg, this[i], i, this); 6 } 7 }
5.1 indexOf() for循环一次
1 Array.prototype.distinct5_1 = function (){ 2 var arr = this, 3 result = [], 4 i, 5 len = arr.length; 6 7 for (var i = 0; i < len; i++) { 8 if (result.indexOf(arr[i]) === -1) { 9 result.push(arr[i]); 10 } 11 } 12 return result; 13 };
5.2 indexOf() 结合 forEach(),原数组从第i项开始,只有一个
1 Array.prototype.distinct5_2 = function (){ 2 var arr = this, 3 result = [] ; 4 arr.forEach(function(e, i, arr) { 5 if (arr.indexOf(e) === i) { //indexOf判断元素的值是否与当前索引相等 6 result.push(e); 7 } 8 }); 9 10 return result; 11 };
5.3 indexOf() 结合 forEach(),原数组第i项与第i+1项开始比较,未找到返-1
1 Array.prototype.distinct5_3 = function (){ 2 var arr = this, 3 result = [], 4 len = arr.length; 5 arr.forEach(function(e, i ,arr){ //这里利用map,filter方法也可以实现 6 var bool = arr.indexOf(e,i+1); //从传入参数的下一个索引值开始寻找是否存在重复 7 if(bool === -1){ 8 result.push(e); 9 } 10 }); 11 return result; 12 };
1 var arr5 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 2 console.log(arr5.distinct5_1()); //[1, "1", true, "true"] 3 console.log(arr5.distinct5_2()); 4 console.log(arr5.distinct5_3());
6.ES6 ... Set()
1 var arr6 = [1,1,‘1‘,‘1‘,true,true,‘true‘,‘true‘]; 2 var arr=[...new Set(arr)]; 3 console.log(arr); //[1, "1", true, "true"]
小结,去重方法很多,个人建议直接第五种方法,运行效率会高些,不过ES6的方法更是简单霸气;这6种方法只是js源码,在开发工作中看到的往往都是封装好的,不过基础还是要夯实,才能应对前端框架更新如此快的节奏,轻松上手。。。欢迎指正。
原创文章,转载注明出处。