JavaScript 普通数组去重 & 对象数组去重 (自定义equals函数实现灵活去重)

实现数组去重的方法有很多, 如果不考虑兼容性, 可以直接用ES6的 Set展开运算符… 实现。但如果遇到了需要根据实际情况特殊处理的, 就需要用到比较原生的方式去灵活实现。

/**
 * 初始数据arr
 */
const arr = [
    {a:1,b:2},
    {b:2,a:1},
    {a:1,b:2,c:{a:1,b:2}},
    {a:1,b:2,c:{b:2,a:1}},
]

先来看一下用Set()去重:

/**
 * Set方法去重
 */
const newArr = [...new Set(arr)];
console.log(newArr);
//对象数组去重
//对象均为 Plain Object
//只要对象的所有属性值相同, 则表示相同对象

/**  输出
[
  { a: 1, b: 2 },
  { b: 2, a: 1 },
  { a: 1, b: 2, c: { a: 1, b: 2 } },
  { a: 1, b: 2, c: { b: 2, a: 1 } }
] 
显然, 这里用set无法实现对象数组去重
*/

再来看一下比较原生的数组去重方法:

/**
 * 最原始的去重方法
 */
const newArr02 = [...arr];
for(let i=0;i<newArr02.length;i++){
    for(let j=i+1;j<newArr02.length;j++){
        if(newArr02[i]===newArr02[j]){ // ===严格对等, 和set的原理一致
            newArr02.splice(j,1);
            j--;
        }
    }
}

console.log(newArr02);
/**  输出
[
  { a: 1, b: 2 },
  { b: 2, a: 1 },
  { a: 1, b: 2, c: { a: 1, b: 2 } },
  { a: 1, b: 2, c: { b: 2, a: 1 } }
] 
显然, 这里和Set去重的输出一致, 统一无法实现对象数组去重
*/

这里的方法的核心在于: newArr02[i] === newArr02[j] , 如需修改判断去重的逻辑, 修改此处即可

// 创建数组的副本,避免修改原始数组
const newArr03 = [...arr];

// 辅助函数,判断一个值是否为对象
const isObject = (obj) => typeof obj === 'object' && obj!== null;

// 通过自定义 equals 函数来比较数组中的元素,并去除重复元素, 实现灵活去重
for(let i=0;i<newArr03.length;i++){
    for(let j=i+1;j<newArr03.length;j++){
        if(equals(newArr03[i],newArr03[j])){ //
            newArr03.splice(j,1);
            j--;
        }
    }
}

/**
 * 比较两个值是否相等。
 * 如果两个值都是对象,则比较它们的属性是否相等。
 * 如果两个值不是对象,则直接比较它们的值是否相等。
 *
 * @param {any} val01 - 要比较的第一个值。
 * @param {any} val02 - 要比较的第二个值。
 * @return {boolean} - 如果两个值相等,返回 true,否则返回 false。
 */
function equals(val01,val02){
    if(isObject(val01) && isObject(val02)){
        const keys01 = Object.keys(val01);
        const keys02 = Object.keys(val02);
        // 如果两个对象的键的数量不同,则它们不相等
        if(keys01.length!== keys02.length){
            return false;
        }
        // 遍历第一个对象的所有键
        for(const k of keys01){
            // 如果第二个对象不包含当前键,或者对应的值不相等,则它们不相等
            if(!keys02.includes(k) ||!equals(val01[k], val02[k])){
                return false;
            }
        }
        // 如果所有键和对应的值都相等,则两个对象相等
        return true;
    }else{
        // 如果两个值不是对象,则直接比较它们的值
        return val01 === val02;
    }
}

// 打印去重后的数组
console.log(newArr03);
/**  输出
[ { a: 1, b: 2 }, { a: 1, b: 2, c: { a: 1, b: 2 } } ]
通过自定义的equals方法实现了对象数组去重
*/

最后, 总结JavaScript中比较常见的9种数组去重方法:

  1. 利用 Set() 去重:代码简洁,不考虑兼容性,无法去掉 {} 空对象。
  2. for 嵌套 for 结合 splice 去重:双层循环,外层循环元素,内层比较值,{}、NaN 无法去重,两个 null 消失。
  3. 利用 indexOf 去重:新建空结果数组,通过判断是否存在当前元素决定是否添加,{}、NaN无法去重。
  4. 利用 sort() 去重:先排序再比对相邻元素,{}、NaN无法去重。
  5. 利用 includes() 去重:通过检测数组是否有某个值进行去重,{}无法去重。
  6. 利用 hasOwnProperty 去重:利用对象属性判断,所有元素都能去重。
  7. 利用 filter 去重:通过索引比对去重,{}无法去重。
  8. 利用递归去重:通过递归和排序进行去重,{}、NaN 无法去重。
  9. 利用 Map() 去重:创建 Map 存储 key 值实现去重, {}、NaN无法去重。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值