DEV Community

Cover image for How to Compare Objects in JavaScript
Simon Ugorji
Simon Ugorji

Posted on

How to Compare Objects in JavaScript

Today, I am going to show you a basic way to write a function that compares (2) objects, and also retrieves their matching properties.

compareObject

This function as the name states will be used to compare 2 objects and it works for objects that contain simple, but not complex properties.

A complex property, in this case, can be seen as a property in which their values contain arrays or other objects within them.

Quick Memory Refresh on Objects

Before we begin, let us refresh our memory on JavaScript Objects.

js-object.png

Say, we have the object below;

const user = {
    "uid" : 12345,
    "name" : "simon",
    "loc" : "NG"
}

Enter fullscreen mode Exit fullscreen mode

To access the value of any property, we will make use of the key.

To list out all keys contained in this Object, we will do something like this;

console.log(Object.keys(user));
/* ['uid', 'name', 'loc'] */

Enter fullscreen mode Exit fullscreen mode

Now, depending on the property we wish to access, we will make use of their respective keys to access them.

Let's access the user's uid (user_id), name, and location.

console.log(user['uid']);
//12345
console.log(user['name']);
//Simon
console.log(user['loc']);
//NG

Enter fullscreen mode Exit fullscreen mode

Since we can't directly use the length method to find out how many properties are contained in the object, we have to list out the keys first and then find out how many keys were listed out. In this way, we have the total properties contained in the object.

console.log(Object.keys(user).length);
//3

Enter fullscreen mode Exit fullscreen mode

Having a basic knowledge of objects, let's write our function that compares two objects and returns true if they are equal, and false if they are not.

We will start off by checking if the parameters provided are Objects.

The arrow function below returns true if it is an object or false if not.

const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
}
Enter fullscreen mode Exit fullscreen mode

Then we check if the length of the first object equals the length of the second object.

This is because when comparing two things, in this case, Objects, they must have equal lengths and equal properties.

function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

}

Enter fullscreen mode Exit fullscreen mode

Now, we will loop through the first object, to compare its properties (key and value), one by one with the second object.

We will also create a variable that stores the number of matched properties, and then we will check if the number of matched properties equals the length of the object. If they are equal, we will return true which means that the two objects provided are equal.

function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

    let match = 0; //store number of matched properties
    Object.keys(obj1).forEach(i => {
        //check if values with the same keys are equal
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
        }
    })
    //check if length equals the number of matched properties
    if(match === len){
        return true;
    }

    return false;
}

Enter fullscreen mode Exit fullscreen mode

Testing our compareObject Function

In other to test this function, we will create 4 Objects. Two Objects will contain the same properties (a and d) and the other two will contain unequal properties (b and c). Then we will call the function and pass in the variables.

Here's the full script

const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
}

function compareObject(obj1, obj2){
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length; //use any length
    }

    let match = 0; //store number of matched properties
    Object.keys(obj1).forEach(i => {
        //check if values with the same keys are equal
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
        }
    })
    //check if object length equals the number of matched properties
    if(match === len){
        return true;
    }

    return false;
}
Enter fullscreen mode Exit fullscreen mode

Let's call the function

const a = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}
const b = {"name" : "ugorji", "age" : 6, "loc" : 'NG', "sex" : "male"}
const c = {"name" : "okorie", "age" : 7, "loc" : 'NG', "sex" : "male"}
const d = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}

//check b and c -> unequal
compareObject(b, c);

//check a and d -> equal
compareObject(a, d);

Enter fullscreen mode Exit fullscreen mode

Comparing b and c

image.png

Comparing a and d

image.png

What Next?

We have completed our function that checks if two objects are equal. It returns true if equal and false if unequal. We can extend the function to list out properties that are contained in both objects.

We can use this to list out the matching properties contained in the objects.

Let us edit our function

We will create a variable of type object, that will store the matched properties (ie. properties contained in the first object and in the second object).

Then inside the block that confirms if both properties are equal, we will append the key and value of the matched property.

function compareObject(obj1, obj2){
    //comparing obj with obj2
    if(!isObject(obj1) || !isObject(obj2)){
        return false;
    }

    let len = null;
    //check if they're of thesame length
    if(Object.keys(obj1).length != Object.keys(obj2).length){
        return false;
    }else{
        len = Object.keys(obj1).length;
    }

    //check against obj2
    let i = 0;
    let match = 0;
    //store matched properties
    let matchVal = {};
    Object.keys(obj1).forEach(i => {
        if(obj1[i] === obj2[i]){
            match++; //increment the variable
            //append key and value to the variable
            matchVal[i] = obj1[i];
        }
    })
    console.log(matchVal); //show the matched properties
    //check if the number of properties matched = the length of the object
    if(match == len){
        return true;
    }

    return false;
}

Enter fullscreen mode Exit fullscreen mode

Now let us test the function again by comparing the previous unequal objects. The function should list out the matched properties of the two objects, and return false since they are unequal.

const a = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}
const b = {"name" : "ugorji", "age" : 6, "loc" : 'NG', "sex" : "male"}
const c = {"name" : "okorie", "age" : 7, "loc" : 'NG', "sex" : "male"}
const d = {"name" : "simon", "age" : 5, "loc" : 'NG', "sex" : "male"}

//check unequal objects
compareObject(b, c);

Enter fullscreen mode Exit fullscreen mode

comparing objects b and c

image.png

It works!!!

Wrapping Up

If your Object's property contains a value that is either an object or an array, the comparison operator (===) will return false because we can't directly compare 2 objects or arrays using the operator.

image.png

image.png

In this case, you will have to check if the value is an array or an object, then loop through its values, in order to bring it down to a comparison level. Or you could convert the two data structures to JSON strings with the JSON.stringify() function and then compare them.

A guide using JSON.stringify

The function above works perfectly for shallow objects and this means that the properties in the object should contain a key and a value that is either a string or a number. But if the object property contains a key and a value which is either an array or an object, the function above, won't help out.

Using the function below, you can compare any type of object, as long as you don't need to retrieve its matching properties (content for another day).

The Logic behind the function below is basically just using JSON.stringify to convert the object to a JSON string, save the results to a variable, then loop through each character and check if it exists in the other object using the includes method.

I got this suggestion from Sunil and I am happy that it solves the problem.

Lets Begin

  • First, we need to check if the provided variable is an object 
  • Then we check if the length of the first object equals the second object
function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, we will create a match variable that will store the number of characters that are matched, and then a stringified variable that will store the results of converting the first object to a JSON string using JSON.stringify.

function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
  let match = 0; //store number of matched properties
  let stringified = JSON.stringify(obj1); //use JSON.stringify to convert to JSON string
}
Enter fullscreen mode Exit fullscreen mode

Now, we have to loop through the stringified variable and check if each character is contained in the second object stringified. If a match is found, we will increment the match variable, and after the loop, we will check if the match variable equals the length of the stringified object.

The reason I chose to use the includes method and not the comparison operator to check this is because of two equal objects like this;

image.png

Both objects above are equal, but the property value of the second object is an array containing the same values as the first object but in a reverse manner. So if a comparison operator is used to compare this, the result will be false.

That is why I chose to use the includes method to check if the character is included in the second object stringified.

function compareObject(obj1, obj2){
  const isObject = (obj) => {
    return (Object.prototype.toString.call(obj) === '[object Object]');
  }
  if(!isObject(obj1) || !isObject(obj2)){
    return false;
  }
  let len = null;
  //check if they're of thesame length
  if(Object.keys(obj1).length != Object.keys(obj2).length){
    return false;
  }else{
    len = JSON.stringify(obj1).length; //use any length
  }
  let match = 0; //store number of matched properties
  let stringified = JSON.stringify(obj1); //use JSON.stringify to convert to JSON string

  let ii = 0;
  //loop through the variable
  while( ii < stringified.length){
    //check if character exists in the other object
    if(JSON.stringify(obj2).includes(stringified[ii])){
      match++; //increment the variable
    }
    ii++;
  }
  //check if object length equals the number of matched properties
  if(match === len){
    return true;
  }
  return false;
}

Enter fullscreen mode Exit fullscreen mode

TESTING

Using our new function, We will start off by comparing the example above, then we will compare an object that contains a complex property (which is the main reason for this post).

Comparing the example above

compare_object

Comparing an object with a complex property

const obj1 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [7,8,9]},
        {'og-id' : 5, 'opt-ids' : [10,11,12]}
    ]
}
const obj2 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [9,7,8]},
        {'og-id' : 5, 'opt-ids' : [11,10,12]}
    ]
}
const obj3 = {
    recipeId : 1,
    count : 1,
    optionGroups : 
    [
        {'og-id' : 1, 'opt-ids' : [7,8,10]},
        {'og-id' : 5, 'opt-ids' : [10,11,12]}
    ]
}
Enter fullscreen mode Exit fullscreen mode

compare_object

Looking at the results in the image above, we can say that the objects obj1 and obj2 are equal!

I hope you have found this useful. Feel free to drop your questions, corrections, or suggestions using the comment box below.

Thank you!

Top comments (0)