JS中数组去重的八种方法


1、利用for嵌套for,然后splice去重

let arr = [1, 3, 7, 10, 10, 1, true,true,false,'true',null,{a:'1'},{a:'1'},
null,undefined,undefined,NaN,NaN];
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); // 删除与第一个数比相等的数
            i--; //   因为删除了需要重新比较
        }
    }
}
console.log(arr);//[1, 3,  7, 10, true, false,'true', null, { a: '1' }, { a: '1' },undefined, NaN,NaN]
 //这种方法利用了双层循环,外层循环元素,内层循环时比较值,如果值相同时则删除这个值, //同时这个方法会改变原数组
这种方法没有把对象类型和NaN重复的遍历掉 
2、indexOf去重,也是最常用的
let arr = [1, 3, 7, 10, 10, 1, true,true,false,'true',null,{a:'1'},{a:'1'},
null,undefined,undefined,NaN,NaN];
let temp =[];
for(let i = 0 ; i < arr.length; i++){ 
    if(temp.indexOf(arr[i]) === -1){  // temp.indexOf(arr[i]) 通过数组的下标查找没有查找的值,始终为-1
        temp.push(arr[i]);   // temp数组没有相同的值,就加入数组。反之
    }
}
console.log(temp);//[1, 3,  7, 10, true, false,'true', null, { a: '1' }, { c: '1' },undefined, NaN,NaN]
//这个方法不会改变原数组,这时候需要创建一个新数组,利用数组的indexOf方法判断新数组里面是否有原数组的元素,当返回结果是-1时,证明该元素不存在新数组内,再将元素添加到新的数组里面。

这种方法也没有把对象类型和NaN重复的遍历掉 ,原因是indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。

3、利用includes去重
let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined,NaN,NaN];
let temp = [];
for(let item of arr){  
     if(temp.includes(item) == false){   // 通过遍历的值,去查找新数组是否有该值,返回的是false就没有,加入新数组。反之
         temp.push(item);
   }
}
 console.log(temp);//[1, 3,  7, 10, ,'A',true, false,'true', null, { a: '1' }, { a: '1' },undefined, NaN]

则同上一个indexOf方法相比就没有这个问题。但是对象还是不能被遍历掉

[NaN].includes(NaN)// true

4、利用new set()方法去重

//对象不能被遍历掉
let arr = [{a:1}, {a:2}, {a:2}, {a:3},1,1,2,2,3,5,5,NaN,NaN];  //[{a:1},{a:2},{a:2},{a:3},1,2,3,5]
let set = new Set(arr);
let newArr = Array.from(set);
console.log(newArr); //[{a:1},{a:2},{a:2},{a:3},1,2,3,5,NaN]

//这种时候对象可以被遍历掉,并且NaN也可以过滤掉
const b={a:2}
let arr = [{a:1}, b, b, {a:3},NaN,NaN,1,1,2,2,3,5,5];  //[{a:1},{a:2},{a:2},{a:3},1,2,3,5]
let set = new Set(arr);//去掉重复数据,返回结果是'set'
let newArr = Array.from(set); //将set转化为数组
console.log(newArr); // [ { a: 1 }, { a: 2 }, { a: 3 }, NaN ,1,2,3,5]

Set类似于数组,区别在于它所有的成员都是唯一的,不能有重复的值

5、利用数组中的filter方法

let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined,NaN,NaN];
let result = arr.filter(function(value,index,self){
    return self.indexOf(value) == index;   // 数组中的每个元素执行相同的函数,将结果组合成一个新数组。
})
console.log(result)

利用数组中的filter方法.filter()接收的回调函数,其实可以有多个参数。通常我们仅使用第一个参数element,表示Array的某个元素。回调函数还可以接收另外两个参数,表示元素的位置index和数组本身self.

filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

filter去除重复元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉了。但此时NaN则全被过滤掉

6、利用Map数据结构去重

let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined,
NaN,NaN,NaN];
let map = new Map();   // 利用Map的数据结构去重
let temp = [];
for (let i = 0; i < arr.length; i++) {
    if (!map.has(arr[i])) {//has进行值得查找,返回true或false
        map.set(arr[i], true);
        temp.push(arr[i]);
    }
}
console.log(temp);//[1,3,7,10,'A',true,false,'true', null,{ a: '1' },{ a: '1' }, undefined, NaN]

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

7、利用hasOwnProperty

function unique(arr) {
 var obj = {};
 return arr.filter(function(item, index, arr){
 return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
 })
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
 console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //所有的都去重了

hasOwnProperty是js中唯一可以判断一个属性定义在对象本身而不是继承原型链的方法,主要用于判断某个对象中是否有某个属性,返回值为布尔值

8、利用递归去重.

function unique(arr) {
 var array= arr;
 var len = array.length;
 
 array.sort(function(a,b){ //排序后更加方便去重
 return a - b;
 })
 
 function loop(index){
 if(index >= 1){
 if(array[index] === array[index-1]){
 array.splice(index,1);
 }
 loop(index - 1); //递归loop,然后数组去重
 }
 }
 loop(len-1);
 return array;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

这种方法也没有将NaN和对象遍历掉

最后总结:正常number和字符串类型以上几种方法都能遍历掉, 而只有第三、四、五、六、七种方法将NaN值过滤掉了,而同时能把对象值遍历掉的只有第四和第七种方法去判断对象中是否存在某个相同属性,然后遍历掉,得到去重后的效果。还有大家如果有更好的数组去重效果可以补充,互相学习进步

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM