2

I have two objects x,y and i want to compare both of these excluding one of the keys "c"

let x = {a: 5, b: 6, c: "string"}
let y = {a: 5, b: 8, c: "string"}

How i am trying to compare it is -

JSON.stringify(x) === JSON.stringify(y)

Above works but it will compare all keys I want to exclude c in comparison here. What's the best way to achieve this ?

Sofiya rao
  • 86
  • 1
  • 11
  • Here in output i want to have a comparison of just x = {a:5, b:6} and y = {a:5, b:8} – Sofiya rao Mar 03 '22 at 13:42
  • Do you know which are the props that you require to compare? Or, you only know the props that you need to ignore from comparison? – jsN00b Mar 03 '22 at 13:47
  • Does this answer your question? [Javascript- Compare 2 object excluding certain keys](https://stackoverflow.com/questions/68890700/javascript-compare-2-object-excluding-certain-keys) – Heretic Monkey Mar 03 '22 at 13:51
  • @HereticMonkey Thanks the answer is almost close to what i wanted. isEqual and omit did the work for me. – Sofiya rao Mar 03 '22 at 16:20
  • @Sofiyarao I added an answer. Hope it will work as per your expectation. – Debug Diva Mar 04 '22 at 12:34

7 Answers7

3

The following code obtains all the keys from object x, removes c from the list, and then performs the comparison.

let x = { a: 5, b: 6, c: "string" };
let y = { a: 5, b: 6, c: "another string" };

console.log(
  Object.keys(x)
    .filter((key) => key !== "c")
    .every((key) => x[key] === y[key])
);
Yuri
  • 86
  • 5
1

array.sort requires a comparator function. You can use the exact same thing here

function myObjComparator (x, y) {
  if (x.a != y.a) return y.a - x.a;
  return y.b - x.b;
}
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
1

Generally, I would NOT stringify objects in order to compare them. The reason is quite simple and is that you MUST to be sure that the order of the members are the same, otherwise the result won't be correct.

Ex:

// objects are equals
const y = { a: '1', b: '2' }
const x = { b: '2', b: '1' }
// but result is not what you expect
JSON.stringify(x) === JSON.stringify(y) // false

But, if you can ensure that the order of the members is always the same, stringify is fast and a good option.

You can use the spread syntax in order to avoid the "c" property

const remappedX = { ...x, c: undefined };
const remappedY = { ...y, c: undefined };
JSON.stringify(remappedX) === JSON.stringify(remappedY); // true

Or alternatively

const allowedKeys = Object.keys(x).filter((k) => k !== 'c');
JSON.stringify(x, allowedKeys) === JSON.stringify(y, allowedKeys);

More generic method is to loop over Object key or alternatively to entries

for(const key of Object.keys(x)) {
   if (key === 'c') {
      continue;
   }
   if (x[key] !== y[key]) {
         return false;
   }
}
return true;

But, if your object is nested, you need to use a deep equality algorithm, which is of course slower.

More generic answer has been given here

Picchio
  • 425
  • 1
  • 7
1

Thanks everyone for quick responses on my question but below was an easy method from which I could implement the above logic

import omit from "lodash/omit";
import isEqual from "lodash/isEqual";

let x = {a: 5, b: 6, c: "string"},
y = {a: 5, b: 8, c: "string"}

result = isEqual(omit(x, ['c']), omit(y, ['c']))
Sofiya rao
  • 86
  • 1
  • 11
0

What about this?

JSON.stringify(x, ['a','b']) === JSON.stringify(y, ['a','b']);

better solution:

function replacer(key, value) {
  // Filtering out properties
  if (key === 'c') {
    return undefined;
  }
  return value;
}
JSON.stringify(x, replacer) === JSON.stringify(y, replacer);

correct better solution:

const filterKeys = (obj) => Object.keys(y).filter(k => k !== 'c').sort()
JSON.stringify(x, filterKeys(x)) === JSON.stringify(y, filterKeys(y));
zbyso
  • 108
  • 5
0

Here is a solution

const x = {a: 5, b: 8, c: "string1", d: {e: 9}}
const y = {a: 5, b: 8, c: "string2", d: {e: 9}}

const compare = (obj1, obj2, except = []) => {
    
    if (Object.keys(obj1).length < Object.keys(obj2).length) {
        [obj1, obj2] = [obj2, obj1];
    }
    
    for (const obj1Key in obj1) {
        if (except.includes(obj1Key)) continue;

        if (!obj2.hasOwnProperty(obj1Key)) return false;

        if (typeof obj1[obj1Key] === 'object') {
            if (typeof obj2[obj1Key] !== 'object') return false;
            
            const isEqual = compare(obj1[obj1Key], obj2[obj1Key]);
            
            if (isEqual) continue
            
            return false;
        }

        if (obj1[obj1Key] !== obj2[obj1Key]) return false;
    }
    
    return true;
}

console.log(compare(x, y, ['c']));
EzioMercer
  • 1,502
  • 2
  • 7
  • 23
0

Using ternary operator to compare both the objects.

Demo :

let x = {a: 5, b: 6, c: "string"};
let y = {a: 5, b: 8, c: "string"};

function compare(obj1, obj2) {
  return (obj1.a != obj2.a) ? false : (obj1.b != obj2.b) ? false : true;
}

console.log(compare(x, y));

By deleting the unwanted properties and then compare using JSON.stringify()

Demo :

let x = {a: 5, b: 6, c: "string"};
let y = {a: 5, b: 8, c: "string"};

delete x.c;
delete y.c;

console.log(JSON.stringify(x) === JSON.stringify(y));
Debug Diva
  • 26,058
  • 13
  • 70
  • 123
  • This would work but in the case where there is a change in order of the json.. Stringify would miss that case and just compare two strings. I have answered this question, but thanks I will be able to use this logic in some other usecase – Sofiya rao Mar 04 '22 at 20:39