数组去重涉及基础知识较多,总结了以下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--; //原数组长度减111 j--; //内部循环索引减112 }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() 方法
Array.prototype.indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, j = this.length; i < j; i++) { if (this[i] === item) { return i; } } return -1; //未匹配返回-1};
兼容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源码,在开发工作中看到的往往都是封装好的,不过基础还是要夯实,才能应对前端框架更新如此快的节奏,轻松上手。。。欢迎指正。
原创文章,转载注明出处。