问题:将一个数组元素去重。
假设我们的数组为
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{name:"zhangjie"},{name:"zhangjie"}];
去重的方法很多,笔者这里主要总结了7种方法。
第一种:采用Set去重(ES6)
let f1 = (arr)=>{ return Array.from(new Set(arr)); }
Array.from()
方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
缺点:该方法无法去除{name:"zhangjie"}元素。
第二种:采用算法的实习思想采用双重遍历去重。
let f2 = (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); } } return arr; }
该方法容易想到。
缺点:无法去掉NAN与{name:"zhangjie"}。
第三种:采用indexof()去重。
let f3 = (arr)=>{ if(!Array.isArray(arr)) { console.log("Type Error"); } let arr1 = []; for(let i =0;i<arr.length;i++) { if(arr1.indexOf(arr[i])==-1) { arr1.push(arr[i]) } } return arr1; }
该方法的思想是查找arr1中是否存在arr中的元素,不存在则将该元素push到数组中去。
缺点:无法去除NAN与{name:"zhangjie"}。
第四种:排序的方式。
let f4 = (arr)=>{ if(!Array.isArray(arr)) { console.log("Type Error"); } arr = arr.sort(); let arr1 =[arr[0]]; for(let i = 1;i<arr.length;i++) { if(arr[i]!==arr[i-1]){ arr1.push(arr[i]); } } return arr1; }
将数组排序后,通过前后比较,如果不相同,就将去push到arr1中去。
缺点:无法去除NAN与{name:"zhangjie"}。
第五种:采用includes的方法去重。
let f5 = (arr)=>{ if(!Array.isArray(arr)) { console.log("Type Error"); } let arr1 = []; for(let i =0;i<arr.length;i++) { if(!arr1.includes(arr[i])) { arr1.push(arr[i]) } } return arr1; }
该方法也是采用的如果arr1中不存在arr中的元素,就将该元素push到arr1中去。
缺点:无法去掉{name:"zhangjie"}。
第六种:filter去重。
let f6 = (arr)=>{ return arr.filter((item,index,arr)=>{ return arr.indexOf(item,0) === index; }) }
缺点:不能去除{name:"zhangjie"},而且会将NAN与"NAN"当成一样的。
第七种:利用对象的hasOwnProperty方法
let f7 = (arr)=>{ var obj = {}; return arr.filter((item)=>{ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) }) }
缺点:无。不过该方法是有一个奇怪的地方。
let obj= { 1:"zhangsan" }; let obj1= { "1":"zhangsan" }
例如我声明了两个对象,一个属性名是数字,一个属性名是字符串。当我打印的时候。
会发现是一样的,这也就是为什么用obj[typeof item +item] = true而不用obj[item] = true。