繁体   English   中英

比较两个对象的值的最有效方法是什么?

[英]What's the most efficient way to compare values of two objects?

假设我有两个对象,它们可能有一些共同的属性。 总体思路是,将一个用作模式以将其与另一个进行比较。 我想比较常见属性的值并构造一个新对象来表示每个单独属性的这些比较。 结果,任何共同的属性都应该具有比较源属性是否相等的值(例如result.abc = (obj1.abc == obj2.abc) )。 仅存在于两个对象之一上的任何属性都将以其原始值复制到结果中。

例如,考虑以下要比较的对象:

const schema = {
        num: 123,
        str: 'hello',
        nested: {
            num: 123,
            str: 'hello',
        },
    },

    doc = {
        nums: [1,2,3],
        str: 'hello',
        nested: {
            num: 123,
            str: 'world',
            foo: 'bar',
        },
    };

比较结果应该是:

{
    nums: [1,2,3], // obj2.nums
    num: 123,  // obj1.num
    str: true, // obj1.str == obj2.str
    nested: {
        num: true,  // obj1.nested.num == obj2.nested.num
        str: false, // obj1.nested.str == obj2.nested.str
        foo: 'bar', // obj2.nested.foo
    },
}

我将如何以最有效的时间和空间方式进行这种比较?

目前我有这个实现:

function deepCompare(obj1, obj2) {
    const validatedObject = {}

    Object.keys(obj1).forEach(e => {
        if(object[e].constructor.name === 'Object') {
            validatedObject[e] = deepCompare(obj1[e], obj2[e])
        } else {
            validatedObject[e] = obj1[e] === obj2[e]
        }
    })

    return validatedObject
}

是否有任何方法可以在不使用JSON.stringify的情况下更有效地执行此操作,因为我可能缺少属性,但我仍然想返回values是正确的事实,尽管这些对象的架构是正确的?

也许for infor of循环? 但是我将如何测试它们的有效性呢? 小物体没关系,但有时它们会变得非常大,我想以最有效的方式比较它们。

编辑注意

我知道这可能看起来像重复,但实际上并非如此,在这里我正在寻找一种最有效的方法来比较,迭代,递归或其他方式,而不是对象本身

逻辑是如果obj1有一个键并且obj2有相同的键,我们比较这些键的值

那么你应该使用

function compare(a, b) {
    if (a === b) return true;
    if (typeof a == 'object' && a != null && typeof b == 'object' && b != null) {
        return Object.keys(a).every(k =>
            !(k in b) || compare(a[k], b[k])
        );
    }
    return false;
}

我认为您的解决方案已经足够好了,它只是缺少一些默认检查(例如,如果您有相同的引用,则不需要遍历对象键)。

此外,还有这个包声称是最快的深度相等检查器。

在此处输入图像描述

您可以查看代码以查看是否遗漏了任何其他条件(它仍然是对象的递归解决方案,但如果您感兴趣,还可以在那里处理一些其他数据类型)。

如果您更喜欢书面材料而不是在递归调用之前有更多检查的代码,那么还有这篇文章

您要做的是首先找到公共对象键。 然后,当您遍历属性时,您希望在发现不匹配时立即返回 false。 在下面的代码片段中,我使用了一个every循环,一旦一次迭代返回false就会停止。 如果在if块中返回值,则不需要else块。

 function deepCompare(obj1, obj2) { const commonKeys = Object.keys(obj1).filter(x => Object.keys(obj2).includes(x)); let valid = true; commonKeys.every(e => { if (obj1[e].constructor.name === 'Object') { console.log('object', e, obj1[e], obj2[e]) valid = deepCompare(obj1[e], obj2[e]) return valid // true goes to next, false ends the .every loop } console.log('not object', e, obj1[e] === obj2[e] ? 'match' : 'mismatch') valid = obj1[e] === obj2[e] return valid // true goes to next, false ends the .every loop }) return valid // returns the first false or true if everything passes } const obj1 = { num: 123, str: 'hello', nested: { num: 123, str: 'hello', } } const obj3 = { num: 1233, str: 'hello' } const obj4 = { num: 123, str: 'hello', nested: { num: 123, str: 'hellure', } } console.log(deepCompare(obj1, obj1.nested)) console.log(deepCompare(obj1, obj3)) console.log(deepCompare(obj1, obj4))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM