数组去重方法

1、最简化的方法是使用ES6的set去重,set是一个集合,集合中元素不允许重复,将数组转化为集合再还原成数组就会自动去重。

let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]
[...new Set(arr)]
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}] 空对象未去重

2、reduce+includes,有些会认为reduce写出来的代码可读性比较差,难以理解,但个人认为reduce的功能还是很强大的,比较灵活,有些时候还可以提高性能,将两层循环转化为一层循环,(这里去重并没有提高性能,只是一种方法供参考)

let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]
arr.reduce((result,cur)=>result.includes(cur)?result:[...result,cur],[])
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}] 空对象未去重

3、使用Map,用空间换时间。reduce+includes实际上是两层循环,如果想用一层循环去重,可以使用Map映射。但这种方法就多定义了一个Map,额外占用了空间。这里的Map不能用对象替换,因为对象的key只能是字符串,用数组元素作为对象的key时,会自动转化为字符串,从而出现bug

let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]
var map = new Map()
var newArr = []
arr.map((item)=>{
    if(!map.has(item)){
        map.set(item,item)
        newArr.push(item)
    }
    return item
})
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}] 空对象未去重

4、使用两层map循环+splice。遇到重复元素就用splice删除。这种方法比较笨,就不再写了

5、sort+for循环。先对数组进行排序,再循环数组,比较当前元素与上一个元素是否相等,不相等则放入新数组。 由于NaN!==NaN,所以该方法去不掉NaN

let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]
arr = arr.sort()
let newArr = [arr[0]]
for(let i=1;i<arr.length;i++) {
    if(arr[i]!==arr[i-1]) {
         newArr.push(arr[i]) 
    }
}
// [0, 1, 15, NaN, NaN, "NaN", {}, {}, "a", false, null, "true", true, undefined] NaN和空对象未去重

6、for循环+indexOf。循环原数组,用indexOf方法比较当前元素index在新数组中是否存在,不存在则放入新数组。该方法实际也是两层循环(因为indexOf也会进行一层循环),不是很好,就不写了。 

7、以上的方法对于简单类型的数组去重可行,但对于有对象的数组就不能去重了,两个空对象和两个空数组都不能去重。因此,对于复杂的数组需要递归判断元素类型。

// 判断两个变量是否相等,{}与{},[]与[]相等
function isObjectValueEqual(a, b) {
    // 如果a或b不是对象,或者a或b为null,则直接对比
    if(typeof a !== 'object' || typeof b !== 'object' || a===null || b===null) {
       return a===b
    }
     //获取a和b的属性名称
     var aProps = Object.getOwnPropertyNames(a);
     var bProps = Object.getOwnPropertyNames(b);
     // 属性名称数组长度不相等,a和b肯定不相等
      if (aProps.length != bProps.length) {
           return false;
      }
      // 长度相等再循环属性值进行比较
      for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i]
        var propA = a[propName]
        var propB = b[propName]
        if ((typeof (propA) === 'object')) {
        // 属性值是对象,则递归判断
          return this.isObjectValueEqual(propA, propB)
        } else { 
        // 属性值不是对象,则根据属性值直接判断
            if (propA !== propB) {
              return false
            }
        }
      }
    // 循环完成,没有返回值说明所有值都相等,返回true
    return true
    }
// 基于方法5 进行去重
let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]
arr = arr.sort()
let newArr = [arr[0]]
for(let i=1;i<arr.length;i++) {
     if(!isObjectValueEqual(arr[i],arr[i-1])) {
        newArr.push(arr[i])
    }
}
// [0, 1, 15, NaN, NaN "NaN", {}, "a", false, null, "true", true, undefined]
// 为了去掉NaN 需要再执行方法1
[...new Set(newArr)]

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值