Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Add filter #53

Open
SergeyPirogov opened this issue Jan 6, 2020 · 7 comments
Open

[Feature request] Add filter #53

SergeyPirogov opened this issue Jan 6, 2020 · 7 comments

Comments

@SergeyPirogov
Copy link

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'
})
@anko
Copy link
Contributor

anko commented Jan 7, 2020

What would the diff call in your example code return? I don't understand yet what "filter" means in this context.

@SergeyPirogov
Copy link
Author

@anko objects will be equal because we ignore phone node

@anko
Copy link
Contributor

anko commented Jan 7, 2020

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.

@papb
Copy link

papb commented Jan 7, 2020

@anko That sounds great!!

@SergeyPirogov
Copy link
Author

You can look at some similar library. They have similar filter https://www.npmjs.com/package/deep-diff#changes

@k-funk
Copy link

k-funk commented May 11, 2021

+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)

@rdsedmundo
Copy link

Also needing this for another use case: ignore word casing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants