1

I am trying to compare two array of objects. Below is my code.

var result = identical([
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"},
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}}
], [
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}},
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"}
]);

console.log(result); // returns false

function identical(a, b) {
    function sort(object) {
      if (typeof object !== "object" || object === null) {
            return object;
        }
        return Object.keys(object).sort().map(function (key) {
            return {
                key: key,
                value: sort(object[key])
            };
        });
    }

    return JSON.stringify(sort(a)) === JSON.stringify(sort(b));
};

I want to know why I am getting result as false while comparing the above two array of objects.

If I pass the below object, the result is true

var result = identical([
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}},
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"}
], [
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}},
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"}
]);

How to compare based on keys alone and without seeing the order of objects ?

3
  • you should account for arrays. Commented Mar 17, 2015 at 13:08
  • @Daniel A. White What do you mean by account for arrays? Commented Mar 17, 2015 at 13:34
  • Your sorting is way of. Try console.log(JSON.stringify(sort(a))); console.log(JSON.stringify(sort(b))); before you return from your function and you'll see they're absolutely not the same. Commented Mar 17, 2015 at 13:35

3 Answers 3

3

One of the solutions I found, is to define a function to test the equality of the objects, and then you need to call that function for each element on the array. this code works fine for me:

Object.prototype.equals = function(x) {
        for(p in this) {
            switch(typeof(this[p])) {
                    case 'object':
                            if (!this[p].equals(x[p])) { return false }; break;
                    case 'function':
                            if (typeof(x[p])=='undefined' || (p != 'equals' && this[p].toString() != x[p].toString())) { return false; }; break;
                    default:
                            if (this[p] != x[p]) { return false; }
            }
        }
        for(p in x) {
            if(typeof(this[p])=='undefined') {return false;}
        }

        return true;
    }

Source : Object comparison in JavaScript

    function identical (arr1, arr2) {

        if(arr1.length != arr2.length) {
            return false;
        }

        var exists = arr1.length;
        for(var i = 0; i<arr1.length; i++) {
            for(var j =0; j<arr2.length ; j++) {
                if(Object.keys(arr1[i]).equals(Object.keys(arr2[j]))) {
                   exists--;
                }
            }
        }

        return !exists;
    }

Now the result of this code is true

var result = identical([
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}},
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"}
], [
    {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}},
    {"depid": "100", "depname": ""},
    {"city": "abc", "state": "xyz"}
]);

Edit :

To compare only keys, you need to use :

Object.keys(arr1[i]).equals(Object.keys(arr2[j])

instead of

arr1[i].equals(arr2[j])

I made the update on the code above.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the solution. But I dont want to check the values. Even this object must return true since keys are same var result = identical([ {"depid": "100", "depname": "role"}, {"city": "abc", "state": "xyz"}, {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}} ], [ {"firstName": "John", "lastName": "Doe", "contactno": {"ph": 12345, "mob": 485428428}}, {"depid": "100", "depname": ""}, {"city": "abc", "state": "xyz"} ]);
I didn't understand, the values you're passing to the function don't have identical values, do you mean, you need to check only keys ?
Yes. Comparing only the keys.
Awesome update. It works! I accept your answer. One more help, any idea on how to update the values of object2 in object1.
can you explain more what you want to do ? do you mean cloning an object into another one ?
|
1

While serializing objects to string the keys aren't guaranteed to be in same order. To compare irrespective of order check this Comparing two json arrays

Comments

1

It fails because a is an array, so sort(a) sorts a with respect to the array indexes. You can try:

 var l = ['a','b'];
 alert(Object.keys(l));

it shows:

0,1

So sort(a) sorts don't put the objects inside in a meaningful order. It does not even care about what is in the array.

It you want to compare arrays of objects, I would suggest to use your function sort on each object of the array, then jsonify each object in the array, then sort the array of strings and compare the two resulting sorted arrays of strings.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.