简体   繁体   中英

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

Let's say I have two objects, which might have some properties in common. The overall idea is that one is used as a schema to compare it to the other. I would like to compare values of common properties and construct a new object representing these comparisons of each individual property. In the result, any properties in common should have the value of comparing the source properties for equality (eg result.abc = (obj1.abc == obj2.abc) ). Any properties that exist on only one of the two objects would be copied to the result with their original values.

For example, consider the following objects to compare:

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',
        },
    };

The comparison result should be:

{
    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
    },
}

How would I perform this comparison in the most efficient time and space way?

Currently I have this implementation:

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
}

Are there any ways to do this more efficiently without using JSON.stringify , because I might have property that is missing, but I still want to return the fact that the values are correct despite the schema of those objects?

Maybe for in or for of loop? But how would I test their effectiveness? It's okay for small objects, but sometimes they get really big and I want to compare them in the most efficient way possible.

NOTE for editors.

I understand that this might seem like a duplicate, but it in fact is not, here I'm looking for a most efficient way to compare values , iteratively, recursively or some other way, not objects themselves

the logic is if obj1 has a key and obj2 has the same key, we compare the values of those keys

Then you should use

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;
}

I think your solution is good enough, it's only missing some default checks (you don't need to iterate through the objects keys if you have the same refference for example).

Also, there's this package that claims is the fastest deep equal checker.

在此处输入图像描述

You can look over the code to see if you missed any other condition (it's still a recursive solution for the objects, but there are some other data types treated there if you're interested).

There is also this article if you prefer written material instead of code that has more checks before recursive calls

What you want to do is first find the common object keys. Then as you loop through the properties you want to return false as soon as you find a mismatch. In the snippet below I'm using an every loop which will stop as soon as one iteration returns false . If you return a value in the if block you do not need the else block.

 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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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