deep-object-diff
deep-object-diff copied to clipboard
[Feature request] Add filter
In order to compare objects, I want to filter some keys. For example:
lhs = {
"name": "a",
"phone": "b"
}
rhs = {
"name": "a",
"phone": "c"
}
diff(lhs, rhs, function filter(node){
return node.name === 'phone'
})
What would the diff call in your example code return? I don't understand yet what "filter" means in this context.
@anko objects will be equal because we ignore phone node
I see!
I played with some possible workarounds in this Observable notebook trying to see if any of them sound good. Performance-wise, none of them would be as good as having a filter function parameter like this. (Have you tried the alternatives, and found the performance to be a problem?)
Perhaps we should pre-empt all similar future queries by letting the passed-in function instead implement completely custom comparison. Ignoring some property is just a subset of that power:
diff(lhs, rhs, function compare(left, right, propertyName, defaultCompare) {
// Compare all properties as normal, except `phone`, which always
// compares as equal.
if (propertyName === "phone") return true
else return defaultCompare(left, right, propertyName)
})
That way when someone asks for e.g. case-insensitive string diff, or filtering a property except when null, or things like that, they can implement any such logic.
@anko That sounds great!!
You can look at some similar library. They have similar filter https://www.npmjs.com/package/deep-diff#changes
+1
I've come across this deep-object-diff lib in the past few years, hoping to find a lib that does everything this one does, plus filtering. I usually end up writing my own diff, since I find the deep-diff lib that @SergeyPirogov mentioned to be overkill.
I'd prefer the simple key-based filtering api like the one suggested: diff(lhs, rhs, key => key === 'phone'), which is similar to Array.prototype.filter usage. If true, skip comparison+further recursion early. But I'd be amenable to returning defaultCompare if necessary.
Also, while I haven't personally had a use for comparing values, I could see how this "fitler" could also be used for custom comparisons, which might be useful if you wanted to compare Dates, or other complex objects.
FWIW, the most common object-diffing usage for me is doing a restful HTTP PATCH that would look something like this:
const PROPS_TO_ALWAYS_INCLUDE = ['id', 'mode'] // could be other identifying keys like 'objectId' or 'mode'
async function patchToServer(urlPath, left, right) {
const payload = diff(left, right, key => PROPS_TO_ALWAYS_INCLUDE.includes(key))
await ServerCall(urlPath, 'PATCH', payload)
}
...
patchToServer('/users/user_123', originalData, userModifiedData)
Also needing this for another use case: ignore word casing.