-4

Yes, there's a plethora of questions with titles similar to this and I can assure you I've tested almost all of them. Everything Google threw at me, I tried. None sufficed.

Considering these two objects:

const o1 = {
  "someProperty": "someValue",
  "anotherProperty": {
    "p1": "v1",
    "p2": "v2"
  }
}

const o2 = {
  "anotherProperty": {
    "p1": "v1",
    "p2": "v2"
  }
}

How do I find the differences between o2 and o1, by top-level keys, I believe, without "destroy" the object by setting properties' values as undefined (honestly, I found that answer, here, preposterous).

Why do I need this? The here depicted o1 contains "all data" and o2 a subset that will be removed so I can perform an update. You can think of if as the inverse of an intersection.

In pseudo-code above, all I want as output is:

const diff = {
  "someProperty": "someValue"
}

Of course, this is an oversimplified example, in the real deal I have many other properties, with different values, always of primitive data-tyes (plain text, integers, booleans...) one-level nested (like o2) or deep down more levels, but always primitive types.

Sounds like a very simple thing but I just couldn't find anything without NodeJS, Lodash, Underscore or whatever other 3rd-party library.

  • 1
    And the actual problem is what exactly? Grab the keys of `o1` and `o2` (`Object.keys()`), find the unique entries in the keys of `o1` and create `diff` from these keys. – Andreas Nov 26 '21 at 12:05
  • 1
    You're talking about top-level keys, so should nested properties also be checked? Say the key stays the same but its nested properties change. Does your desired solution leave this key and its value out of the diff object or not? – Aarni Joensuu Nov 26 '21 at 12:07
  • 3
    What do you mean with *"by top-level keys"*? Maybe you just want `const toRemove = new Set(Object.keys(o2)); const result = Object.fromEntries(Object.entries(o1).filter(([key]) => !toRemove.has(key)));`. – Felix Kling Nov 26 '21 at 12:07
  • Will the Object hold only other Objects or various iteratables like arrays? – D.Schaller Nov 26 '21 at 12:09
  • 1
    Please don't just write that you tried everything, show us actual examples of the codes you've tried and how they didn't work for your particular case. Also include links to the answers you've found. – Bergi Nov 26 '21 at 12:10
  • 1
    (With some minor adjustments a) Duplicate of: [How to get a subset of a javascript object's properties](https://stackoverflow.com/questions/17781472/how-to-get-a-subset-of-a-javascript-objects-properties), especially with that answer: https://stackoverflow.com/a/56592365/402037 – Andreas Nov 26 '21 at 12:10
  • 1. As I've stated, no libraries, please. 2. Though that *might* have become a little unclear, as stated, the difference. Think of it as in our Math classes back in school. 3. I've mentioned "top-level' because, honestly, I didn't know I better way to describe it. In my case, if present, of course, keys will always be the same, but values may change. –  Nov 26 '21 at 12:21
  • 4. Your example yielded me `Set [ "auth" ]`. I'm not exactly sure how this could help me perform the data update I need of the `o1` without the `o2`. 5. Plain Objects and Arrays are yes, but not all iterable resources. 6. I couldn't post every single attempt because otherwise the question would become enormous and we all know what happens with too long questions: either they're forgotten or closed as "too broad" –  Nov 26 '21 at 12:21
  • 1
    @BrunoAugusto Still, at least show your best attempt then, not all of them. Surely you thought you must have been close, and surely you tried to fix the disparities yourself? It should be really simple to take either a ["deep diff" solution](https://stackoverflow.com/q/8572826/1048572) and have it return the full new value where it found an object difference, or to take a ["shallow diff" solution](https://stackoverflow.com/a/37396358/1048572) and use deep equality instead of reference equality for objects. – Bergi Nov 26 '21 at 12:47
  • 1
    _"4. Your example yielded me `Set [ "auth" ]`"_ - If you're talking about the comment from Felix than you're missing the second part `const result = ...` which will definitely not return a `Set` – Andreas Nov 26 '21 at 16:05

1 Answers1

0

You could get the entries and check against. For objects perform the same and check if the result has some keys.

const
    getDifference = (a, b) => Object.fromEntries(Object
        .entries(a)
        .reduce((r, [k, v]) => {
            if (v && typeof v === 'object') {
                let temp = getDifference(v, b[k] || {});
                if (Object.keys(temp).length) r.push([k, temp]);
            } else {
                if (v !== b[k]) r.push([k, v]);
            }
            return r;
        }, [])
    ),
    o1 = { someProperty: "someValue", anotherProperty: { p1: "v1", p2: "v2", p3: 'v3' }, n1: { n2: { n3: 42 } } },
    o2 = { someProperty: "someValue", anotherProperty: { p1: "v1", p2: "v2" } },
    o3 = { anotherProperty: { p1: "v1", p2: "v2" } };

console.log(getDifference(o1, o3));
console.log(getDifference(o2, o3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392