Ivan Goncharov
Ivan Goncharov

Reputation: 93

Check if two objects have common sub-objects

I need to check if two object have common sub-objects. By common I mean that it exact same value, and not just equal values.

Something like:

function haveCommonObects(value1, value2) {
  ...
}

var common = {};
haveCommonObjects({a: common}, {b: {c: common}}) // true
haveCommonObjects({a: 1}, {b: 1}) // false

I need to check large objects, so function should be reasonable efficient. Also I can't change objects, so I can't flag sub-objects with special property. Objects create in 3rd-party library so I can't alter Object.prototype.

Ideal solution would be to get some kind of ID for every object and save it in collection that support fast lookup.

Can I make such function in JS?

Upvotes: 0

Views: 106

Answers (1)

bgoldst
bgoldst

Reputation: 35314

Here's how I would do this:

function haveCommonObjects(a,b) {
    // check if a and b have any object in common, at any depth level
    if (typeof(a) !== 'object' || typeof(b) !== 'object') return false;
    for (var key in a) {
        var o = a[key];
        if (typeof(o) === 'object' && (hasObject(b,o) || haveCommonObjects(o,b)))
            return true;
    }
    return false;
}
function hasObject(x,t) {
    // check if x has a reference to object t, at any depth level
    for (var key in x) {
        var o = x[key];
        if (typeof(o) === 'object' && (o === t || hasObject(o,t)))
            return true;
    }
    return false;
}
function log(msg) { document.getElementById('log').innerHTML += msg+'<br/>'; }

var common = {};
log(haveCommonObjects({a: common}, {b: {c: common}})); // true
log(haveCommonObjects({a: 1}, {b: 1})); // false
<div id="log"></div>

Note: You should add a hasOwnProperty() filter in every for..in loop if you want to exclude inherited properties; see for..in and hasOwnProperty.

Upvotes: 1

Related Questions