'I want to compare two json objects excluding one of the keys from it
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 ?
Solution 1:[1]
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])
);
Solution 2:[2]
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;
}
Solution 3:[3]
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
Solution 4:[4]
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));
Solution 5:[5]
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));
Solution 6:[6]
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']));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yuri |
| Solution 2 | ControlAltDel |
| Solution 3 | Picchio |
| Solution 4 | |
| Solution 5 | |
| Solution 6 |
