对象数组去重

针对去重问题,有这么几种解决方式,如Set,for循环遍历属性值等。

问题如下:

// 对象数组去重,只要对象的所有属性值相同,则表示相同对象。
const arr = [
    { a: 1, b: 2 },
    { b: 2, a: 1 },
    { a: 1, b: 2, c: { a: 1, b: 2 } },
    { b: 2, a: 1, c: { b: 2, a: 1 } },
];

如果使用Set去重,则不会去掉对象属性顺序不一致的一项,因为对象obj1与 obj2两者所引用的地址不同,js判断为不同的对象。

const newArr = [...new Set(arr)];
obj1 = {
    a: 1,
    b: 2
};
obj2 = {
    b: 2,
    a: 1
};
console.log('obj === obj2: ', obj === obj2); // false

 使用传统嵌套for循环判断:

const newArr = [...arr];
for (let i = 0; i < newArr.length; i++) {
    for (let j = i + 1; j < newArr.length; j++) {
        // 判断条件 newArr[i] === newArr[j]
        if (JSON.stringify(newArr[i]) === JSON.stringify(newArr[j])) {
            newArr.splice(j, 1);
            j--;
        }
    }
}

其输出结果也不符合要求,不过我们可以以此为基础,在条件判断上做文章。

代码大体思路实现如下:

const isObject = val => typeof val === 'object' && val != null;
function equals(val1, val2) {
    if (!isObject(val1) || !isObject(val2)) {
        return Object.is(val1, val2);
    }
    if (val1 === val2) return true;

    const val1Keys = Object.keys(val1);
    const val2Keys = Object.keys(val2);

    if (val1Keys.length != val1Keys.length) return false;
    for (const key of val1Keys) {
        if (!val2Keys.includes(key)) return false;

        const res = equals(val1[key], val2[key]);
        if (!res) return false; // 只要有一个属性值不一样,返回false
        console.log('res: ', res);
    }
}

解释:isObject函数用来判断某个值是否为对象,equals函数用来比较两个值是否相同,包括属性名相同但顺序不同的情况。

Object.is()是ECMAScript 6中的一个新方法,用于比较两个值是否相等,参考MDN。

知识的掌握程度决定了你有多少种选择,每天进步一点点。 

你可能感兴趣的:(javascript,对象去重)