2

I'm trying to find a faster way to compare two json objects. Currently, we have a function that has about 7 $.each() calls in it, which I believe is a very inefficient way to do this, but I have no idea how to do it faster. I'll post our function that compares the two objects, and also, a sample of the two objects.

This is just one piece of data from object-1. There are like 4000 of these within the entire object.

{
"aaData": [
 {
  "serial":"LRRFNGHX",
  "model":"Dell Optiplex",
  "os":"Windows NT",
  "man":"Dell",
  "group":"558D",
  "pcName":"LID93740SHD0",
  "department":"HR",
  "customerName":"Bill gates",
  "username":"bgates",
  "deployLocation":"Chicago, IL",
  "currentLocation":"127.0.0.1",
  "cnStatus":"Usable",
  "previousModel":"Gateway",
  "id":"256",
  "enabled":"false"
  }
 ]
}

This is one value from object-2. This object is considerably smaller, with only a maximum of maybe 100 values within object-2.

{
    "team": {},
    "department": {
        "Automotive": "Automotive"
        },
    "os": {},
    "man": {},
    "model": {},
    "cnStatus": {
        "Usable": "Usable"
        }
}

Here is the ugliest function ever. This compares these two objects, and sets the enabled property in the larger object to true for all matches:

function objCompare(){
        newTotal = 0; 
        var typeCount = 0;
        var menuArray = [];
        console.log(JsonObj);
        $.each(menuObject, function (i, type){
            var empty = jQuery.isEmptyObject(type);
            if(empty === false){
                if(typeCount == 0){
                    $.each(type, function (j, subtype){
                        menuArray.push(subtype);
                        $.each(JsonObj, function(key, element){
                            element.enabled = "false";
                            $.each(element, function(key, subelement){                                
                                if( (subelement != null) && (menuArray.contains(subelement.replace(/\s/g, ''))) ){
                                    element.enabled = "true";
                                }
                           });
                        });
                    });
                }else if(typeCount >= 1){
                    $.each(type, function (j, subtype){;
                        menuArray.push(subtype);
                    });
                    $.each(JsonObj, function(key, element){
                        if((element.enabled === "true") && !menuArray.contains(element[i])){
                            element.enabled = "false";
                        }
                    });
                }
                typeCount++;
            }
            if(empty === true){
             if(typeCount === 0){
                $.each(JsonObj, function(key, element){
                    element.enabled = "false";
                    });
                }
            }
        });
    }
Tyler H
  • 471
  • 7
  • 17
  • What do you want to actually know in the comparison of two objects? You've left out that important detail! Do you want to know that each object has exactly the same keys and values for those keys? What if an object has an extra key that doesn't exist in the other object? Do you need to do a deep, nested comparison so if one has an array of object, that the contents of that array or object are the same as in the other object? – jfriend00 Feb 05 '14 at 17:13
  • I want to know if there is a property in object-1 that matches a property in object-2. It needs to be a deep comparison. And the number of keys shouldn't matter, it just needs to see if that key's value exists anywhere in the other object, then set it's property of enabled to "true" – Tyler H Feb 05 '14 at 17:20
  • Do you just want to know if the property exists in both objects? Or if the property and value for that property are the same in both objects? Are you looking for a specific property name? Or just that any property in `obj1` also exists in `obj2` at any depth in the object? Are you ignoring any specific property names that you don't want in the comparison? – jfriend00 Feb 05 '14 at 17:25
  • I'm looking to see if any property in object1 exists at any level anywhere in object2. ALL propteries from object1 are compared against ALL of object2's propteries. – Tyler H Feb 05 '14 at 17:32
  • And you don't care about the property's value, just that it exists in both objects? – jfriend00 Feb 05 '14 at 17:35
  • Correct. Once I find that the property from object1 exists in object2, I'll do something, but it's not relevant to simplifying the property search. – Tyler H Feb 05 '14 at 17:42
  • bear with me. We are checking to see if Object 1 has a match value for an attribute in Object 2. If there is a match, we set the enabled attribute in the matched subObj, in Object 1, to TRUE. It gets a little more complicated when we have multiple entries in Object 2, as seen in the example. We would then need to match ALL values for it to be true. As in the example above where "Automotive" and "usable" must be true. There are cases where there would be multiple departments and in that case, the department match would be 'OR' instead of 'AND'. Such as ("Automotive" OR "HR") AND ("Usable"). – Tyler H Feb 05 '14 at 19:03
  • Your specification is simply not clear enough for someone to write code for and you keep adding more and more requirements as we go. In my answer below, I've shown you how to recursively look at all the properties in an object. You should be able to adapt that logic to do what you want, but it's beyond me to understand what exactly you really want help with. If you want to ask a much more specific question such as "how do I iterate through all first level properties of an object?" or "how do I tell if a property's value contains a nested object or array?", those are easy to answer. – jfriend00 Feb 05 '14 at 19:09

1 Answers1

0

Here's a function that recursively collects all properties in two objects and then returns you an array of any common property names between them. If .length === 0 in the returned array, then there are no common properties. Otherwise, it contains the common property names. If you need to do any further checking, you can obviously add more specifics to this fairly generic function.

If you need to know where the common prop is in the two object, you could change the map to save the parent object instead of just setting it to true, but then you'd have to deal with the issue where there were more than one occurrence of that property. I didn't go to that level of detail because your specification for what you want to do isn't detailed so I left it here with a function that shows how to recursively walk through all properties in an object.

function findCommonProps(obj1, obj2) {
    var map1 = {}, map2 = {};
    var commonProps = [];

    function isArray(item) {
        return Object.prototype.toString.call(item) === "[object Array]";
    }

    function getProps(item, map) {
        if (typeof item === "object") {
            if (isArray(item)) {
                // iterate through all array elements
                for (var i = 0; i < item.length; i++) {
                    getProps(item[i], map);
                }
            } else {
                for (var prop in item) {
                    map[prop] = true;
                    // recursively get any nested props
                    // if this turns out to be an object or array
                    getProps(item[prop], map);
                }
            }
        }
    }

    // get all properties in obj1 into a map
    getProps(obj1, map1);
    getProps(obj2, map2);
    for (var prop in map1) {
        if (prop in map2) {
            commonProps.push(prop);
        }
    }
    return commonProps;
}

Working demo: http://jsfiddle.net/jfriend00/ESBZv/

jfriend00
  • 683,504
  • 96
  • 985
  • 979