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 ?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 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]) );
Method 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; }
Method 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
Method 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));
Method 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));
Method 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']));
Method 7
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']))
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0