Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Javascript object comparison recursion broken

Javascript object comparison recursion broken

Problem

So it seems I've been scratching my head over this for the past few hours.. roughly around 6 hours now and I just can't seem to figure it out. I have looked at various questions/answers on SO but none of them have given me the answer.

Let me start by explaining what this piece of code is SUPPOSE to do. This code will match the Object properties with another object as long as it matches all of the object_layout.


Note: That I want objects to match even if the full object_layout if not provided.

The data object:

var data = {
    "some object" : {
        name: "some object",
        has: "properties",
        types: [
            "some",
            "type",
            "of",
            "array"
        ]
    },

    "another": {
        property: false,
        name: "another",
        object: "here",
        test: "this",
        object: "strings"
    },

    "minimal object": {
        test: "this too"
    },

    "minimal matching object": {
        property: true,
        name: "minimal matching object",
        test: "this",
        object: "strings"
    },

    "matching object": {
        test: "this",
        property: true,
        name: "matching object",
        this_object: { 
            some: "object" 
    }
    }
};



A typeof prototype function that can detect arrays. Will be used later.

Object.prototype.typeof = function(object) {
  if (!object) { return 'undefined' }

    if (typeof(object) === "object" && 'splice' in object && 'join' in object) {
      return 'array';
    }

    return typeof(object);
}



The find function which is a prototype of Object.

Object.prototype.find = function(object_layout) {

  var found_objects;

  for (object in this) { // loop through objects in this object.

    if (object != 'typeof' && object != 'find') { // skip these functions in our object.
      console.log('object: ' + object);

      for (property in object_layout) {

        if (object_layout.hasOwnProperty(property)) {

          var object_type = Object.typeof(object_layout[property]);
          if (object_type == 'string') {

            console.log('Property ' + property);
            console.log('value: ' + object_layout[property]);

            if (object_layout[property] != this[object][property]) { // if object_layout property doesnt exist in object.
            if (found_objects && found_objects[object]) { console.log(object + " removed from found_objects"); delete found_objects[object]; }// if in found_objects then remove.
              console.log("property doesn't exist.");
              break; // break to next object.
            }

            if (!found_objects) { found_objects = {} }
            if (!found_objects[object]) { console.log("Added object: " + object); found_objects[object] = this[object]; }

          } else if (object_type == 'object') { // recurse into object
            console.log('object type: ' + property);
            console.log("Recurse: " + JSON.stringify(this[object][property]));

            if (this[object][property]) {
              this[object][property].find(object_layout[property]); // recurse broken...
            }

            break; // break to next object
          }

        }
      }
    }
  }

  if (found_objects) { return found_objects; }
  return false;
}



The function call:

var results = data.find(
{ 
  test: "this",
  property: true,
  this_object: { 
    some: "object"
  }
};

console.log(results), true, 3));



Output log (Clipped off the last bit)

Added object: matching object
Property property
value: true
object type: this_object
Recurse: {"some":"object"}
object: some
Property some
value: object
property doesn't exist.



Everything seems to be working up until the point of when it recurses, then somehow the object comparison gets all messed up and it doesn't match any longer.

Problem courtesy of: Levi Roberts

Solution

Well after another few hours I managed to make it work and have to say I'm pretty happy with the results. For now, it:

  • adds a prototype to every object so you can use it anywhere. Just require() it once in your app.
  • will smartfully skip over any objects it does not know how to handle.
  • works with strings, numbers, booleans, and recurses objects to find matches.
  • recurses indefinitely for as many levels as you need!

I plan on adding array objects to the list when I get some more time. For now, here is the code. I also plan on making this a module for npm for Node users. Perhaps even upload it to Github. Stay tuned.

Object.prototype.find = function(object_layout) {

    var found_objects;

    for (object in this) { // loop through objects in this object.
        var this_object = object; // place to store the current object.

        if (Object.typeof([this[object]]) != 'function') {

            for (property in object_layout) {
                var this_property = property; // place to store the current property;

                if (Object.typeof(this[this_object][this_property]) != 'function') {

                    if (object_layout.hasOwnProperty(this_property)) {

                        var object_type = Object.typeof(object_layout[this_property]);
                        if (object_type == 'string' || object_type == 'number' || object_type == 'boolean') {

                            if (object_layout[this_property] != this[this_object][this_property]) { // if object_layout property doesnt exist in object.
                                if (found_objects && found_objects[this_object]) { delete found_objects[this_object]; }// if in found_objects then remove.
                                break; // break to next object.
                            }

                            // Add object to found_objects
                            if (!found_objects) { found_objects = {} }
                            if (!found_objects[this_object]) { found_objects[this_object] = this[this_object]; }

                        } else if (object_type == 'object') { // recurse into object

                            if (!this[this_object][this_property]) { //object property doesn't exist
                                if (found_objects && found_objects[this_object]) { delete found_objects[this_object]; }// if in found_objects then remove.
                                break;
                            } 

                            var recurse_object_data = {}
                            recurse_object_data[this_property] = this[this_object][this_property];

                            if (!recurse_object_data.find(object_layout[this_property])) { // recursive property doesn't exist, delete it.
                                if (found_objects && found_objects[this_object]) { delete found_objects[this_object]; }// if in found_objects then remove.
                                break; // break to next object.   

                            } else {
                                // Add object to found_objects
                                if (!found_objects) { found_objects = {} }
                                if (!found_objects[this_object]) { found_objects[this_object] = this[this_object]; }
                            }

                        } else if (object_type == 'array') {


                        } else {
                            //console.log('.find object: ' + object_type);
                        }
                    }

                }
            }
        }
    }

    if (found_objects && found_objects.size() > 0) { return found_objects; }
    return false;
}
Solution courtesy of: Levi Roberts

Discussion

View additional discussion.



This post first appeared on Node.js Recipes, please read the originial post: here

Share the post

Javascript object comparison recursion broken

×

Subscribe to Node.js Recipes

Get updates delivered right to your inbox!

Thank you for your subscription

×