0

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.

Web Nexus
  • 1,150
  • 9
  • 28
yildirima
  • 13
  • 1
  • 3
  • 1
    What output are you expecting? – ellipsis Jan 26 '19 at 22:38
  • 1
    I can't see where you are comparing the values, I only see a comparison between the iterators of the loops... – Shidersz Jan 26 '19 at 22:39
  • The exercise I've been asked is this: "Write a JavaScript program to compare two objects to determine if the first one contains equivalent property values to the second one" I am trying to compare 2 different objects' values' similarities and enter them to "equivalent" arr. I want to enter values regardless of the similarities of their keys. If values are equal, it won't be an issue if relevant properties have different keys. (Although my example shows only comparison of 2 objects which has all the same property keys, I want my function to bring the results regardless of property keys) – yildirima Jan 27 '19 at 08:39

1 Answers1

0

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!

Adrian Pop
  • 1,879
  • 5
  • 28
  • 40
  • Thanks a lot Adrian. I needed to have some research just to understand your solution :) Many thanks for the help! – yildirima Jan 28 '19 at 20:57
  • @yildirima If you have any questions about the code, you may leave them here. If the answer was helpful, you may mark the answer as accepted. – Adrian Pop Jan 28 '19 at 22:53