4

I am having a complex JSON object which I want to compare like below :

$scope.new = [
  {
    "name": "Node-1",
    "isParent": true,
    "text" : [
       {
           "str" : "This is my first Node-1 string",
           "parent":[]
       },
       {
          "str" : "This is my second Node-1 string",
           "parent":[]
       }],
     "nodes": [
      {
        "name": "Node-1-1",
        "isParent": false,
         "text" : [
           {
             "str" : "This is my first Node-1-1 string",
             "parent":[]
           },
           {
             "str" : "This is my second Node-1-1 string",
             "parent":[]
           }],
           "nodes": [
           {
            "name": "Node-1-1-1",
            "isParent": false,
            "text" : [
            {
              "str" : "This is my first Node-1-1-1 string",
              "parent":[]
            },
            {
              "str" : "This is my second Node-1-1-1 string",
              "parent":[]
            }],
            "nodes": []
          }
        ]
      }
    ]
  }
]

But while comparing I want to ignore 1 property also but as I am using Angular.js I don't see any option in angular.equal which will omit that property while comparing 2 object.

 console.log(angular.equals($scope.new,$scope.copy)); 

So while doing research I came with below answer which is using lodash having emit option but problem is I guess omit create a copy and I guess I will have performance degradation in case of lodash.

Exclude some properties in comparison using isEqual() of lodash

So now I am thinking to convert object so string and then do comparison and I guess that will be fast but problem is how I will omit that property while string comparison?

Something like this:

var str1 = JSON.stringify(JSON.stringify($scope.new));

var str2 = JSON.stringify(JSON.stringify($scope.copy));

console.log(str1==str2);

Note: I want to ignore isParent property while comparing 2 object.

What would be the best way to do compare 2 object?

halfer
  • 19,824
  • 17
  • 99
  • 186
I Love Stackoverflow
  • 6,738
  • 20
  • 97
  • 216

2 Answers2

2

Converting to strings is not the best approach in these cases. Keep them as objects.

Using loadash:

const propertiesToExclude = ['isParent'];
let result = _.isEqual(
  _.omit(obj1, propertiesToExclude),
  _.omit(obj2, propertiesToExclude)
);

Using plain AngularJS, create a copy of the objects removing the not needed properties and then compare them:

let firstObj = angular.copy(obj1);
let secondObj = angular.copy(obj2);
const propertiesToExclude = ['isParent'];
function removeNotComparatedProperties(obj) {
  propertiesToExclude.forEach(prop => {
    delete obj[prop];
  });
}

removeNotComparatedProperties(firstObj);
removeNotComparatedProperties(secondObj);
angular.equals(firstObj, secondObj);
quirimmo
  • 9,800
  • 3
  • 30
  • 45
  • Upvoted for your kind efforts towards helping me but dont you think in case of angular we are adding 2 overhead,1 that is loop and delete property and then comparing. 1 thing which solution will be more faster: lodash or angukar approach??? – I Love Stackoverflow Sep 19 '17 at 18:32
  • Let's start saying that for the objects you are using, talk about performances is pretty useless. Same for the length of the array with the properties to exclude for the comparison. Btw, what do you think loadash does inside? magic? They loop over the object's properties and they check them with the properties you passed in. And `_.omit` creates a copy itself of the object (like `angular.copy`). Performances should be pretty the same I guess, but if you want a precise answer, use jsperf, setup your code and test the performances of the two cases: https://jsperf.com/ – quirimmo Sep 19 '17 at 18:39
  • What I would use if it was my case? It depends. If I am already using or I am planning to use loadash somewhere else, I would go with the loadash solution because more compact and shorter. If I should include loadash just for it, I would go through the second one. – quirimmo Sep 19 '17 at 18:42
1

You can use lodash and override the standard comparator used for deep comparison if you use _.isEqualWith:

var objA = {
  isParent: true,
  foo: {
    isParent: false,
    bar: "foobar"
  }
};

var objB = {
  isParent: false,
  foo: {
    isParent: true,
    bar: "foobar"
  }
};

var comparator = function(left, right, key) {
  if (key === 'isParent') return true; // if the key is 'isParent', mark the values equal
  else return undefined;               // else fall back to the default behavior
}

var isEqual = _.isEqualWith(objA, objB, comparator);

console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

To exclude multiple properties, extend the comparator function accordingly:

var comparator = function(left, right, key) {
  if (key === 'isParent' || key === 'anotherKey') return true;
  else return undefined;
}

You could also use a number of different approaches syntactically, depending on what you prefer -- a switch statement, an array that you iterate...

TimoStaudinger
  • 41,396
  • 16
  • 88
  • 94
  • 1
    Upvoted for your kind efforts towards helping me but do you think deep comparision with lodash will be faster than string comparision? – I Love Stackoverflow Sep 19 '17 at 14:10
  • Performance depends on the implementation and will have to be tested. I'm pretty sure that it is not slower than comparing strings, since serialization isn't particularly fast itself. But that aside, you will have to deal with ignoring the `isParent` property during a string comparison as well, so effectively it saves you nothing. – TimoStaudinger Sep 19 '17 at 14:13
  • All right but what if i want to include 2 to 3 properties then how do i include it? – I Love Stackoverflow Sep 19 '17 at 14:56
  • Simply extend the comparator accordingly. – TimoStaudinger Sep 19 '17 at 15:00
  • Ok so if i want to omit property like prop1,prop2 then i have to add 2 more conditions for prop1 and prop2 like you have added for isParent? – I Love Stackoverflow Sep 19 '17 at 15:02
  • I tried to extend comparator for multiple properties but it is not working.Can you please show me how to extend multiple comparator for multiple properties please – I Love Stackoverflow Sep 20 '17 at 06:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/154906/discussion-between-learning-and-timo). – I Love Stackoverflow Sep 20 '17 at 13:56