javascriptjavascript-objectsobject-comparison

Comparing 2 objects' values with nested for loops


var has = {
    name: 'dog',
    surname: 'cat',
    skills : {
        football: true,
        basketball: true,
        volleyball: true
    }
}

var pas = {
    name: 'dolphin',
    surname: 'cat',
    skills : {
        football: false,
        basketball: false,
        volleyball: true
    }
}

function compare(Obj1, Obj2) {
    var values1 = Object.values(Obj1);
    var values2 = Object.values(Obj2);
    var equivalent = [];
    for (var i = 0; i < values1.length; i++) {
        for (var j = 0; j < values2.length; j++) {
            if (i === j ) {
                equivalent.push(values1[i]);
            } 
        }
    }
    console.log(equivalent, values1, values2);

}

compare(has, pas);

I am trying to compare 2 objects by their values using nested for loops. It might not be the best method to use for such a simple comparison but as a new starter, I really would like to know why it's not working properly.


Solution

  • There are some mistakes in your code. First of all, you are comparing i with j, when you actually want to compare some values.

    I'd solve the problem by taking the keys of the object and iterating among them. If both the objects have those keys AND the values are the same, I'll add them to the equivalent array.

    var has = {
      name: 'dog',
      surname: 'cat',
      skills: {
        football: true,
      }
    }
    
    var pas = {
      name: 'dolphin',
      surname: 'cat',
      skills: {
        football: true,
      }
    }
    
    function compare(Obj1, Obj2) {
      var values1 = Object.values(Obj1);
      var values2 = Object.values(Obj2);
      var equivalent = [];
    
      var keys = Object.keys(Obj1);
      keys.forEach(k => {
        if (Obj1.hasOwnProperty(k) && Obj2.hasOwnProperty(k)) {
          if (Obj1[k] === Obj2[k]) {
            equivalent.push(Obj1[k]);
          }
        }
      });
    
      console.log(equivalent);
    }
    
    compare(has, pas);

    However, this won't work for nested objects, as in your case. Why? Because even if the nested objects (skills in your case) have the same values, they are different objects, different references, so the comparison will fail. See how objects comparison in js works here or here.

    In this case, a general recursive solution may work like the one below:

    var has = {
      name: 'dog',
      surname: 'cat',
      skills: {
        football: true,
        basketball: true,
        volleyball: true
      }
    }
    
    var pas = {
      name: 'dolphin',
      surname: 'cat',
      skills: {
        football: true,
        basketball: false,
        volleyball: false
      }
    }
    
    function compare(Obj1, Obj2) {
      var values1 = Object.values(Obj1);
      var values2 = Object.values(Obj2);
      var equivalent = [];
    
      var keys = Object.keys(Obj1);
      keys.forEach(k => {
        if (Obj1.hasOwnProperty(k) && Obj2.hasOwnProperty(k)) {
          if (typeof Obj1[k] === 'object') {
            let recursiveAnswer = compare(Obj1[k], Obj2[k]);
            equivalent.push(...recursiveAnswer);
          } else if (Obj1[k] === Obj2[k]) {
            equivalent.push(Obj1[k]);
          }
        }
      });
      
      return equivalent;
    }
    
    let equiv = compare(has, pas);
    console.log(equiv);

    Here, if I encounter a value that is also an object, I call the function again. The partial answer will be pushed once the recursive call is done. You'll see that the final answer will also contain the true value here, value that is from the football field, since they are equal (in my example). Having true/false values in the array among the cat string may be confusing, so you can actually add the key name instead of the value for the bool fields.

    You could modify the if and the push like this:

    if (typeof Obj1[k] === 'boolean') {
        equivalent.push(`(${k}, ${Obj1[k]})`);
    } else {
        equivalent.push(Obj1[k]);
    }
    

    This will produce the following output:

    [
      "cat",
      "(football, true)"
    ]
    

    Let me know if you have any questions. Cheers!