17

I have two JavaScript arrays orig (the original array of objects) and update (the updated orig array of objects) that have the same length and contain objects, and I want to output the differences between the each pair of objects.

Example:

var orig = [{enabled:"true", name:"Obj1", id:3},{enabled:"true", name:"Obj2", id:4}]; 

var update = [{enabled:"true", name:"Obj1", id:3}, {enabled:"true", name:"Obj2-updated", id:4}];

The output should be: name:"Obj2-updated"

I implemented something but it needs optimization...

for(var prop=0; prop<orig.length; prop++) {
  for(prop=0; prop<update.length; prop++) {
    if(orig[prop].enabled != update.enabled) { console.log(update.enabled) }
    if(orig[prop].name != update[prop].name) { console.log(update[prop].name) }
    if(orig[prop].id != update[prop].id) { console.log(update[prop].id) }
  }
}
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Valip
  • 4,440
  • 19
  • 79
  • 150
  • is the output a string, or an object? or an array with objects or strings, or? – Nina Scholz Aug 22 '16 at 08:51
  • While I don't know your use-case it seems non-useful to me to have only a list of changed values, without knowing which key and in which object that changed value exists; are you sure you don't need more details? I'm not trying to belittle your question, but I'm trying to anticipate what your next question might be, if you're wrong about only needing the changed value(s). – David Thomas Aug 22 '16 at 08:51
  • I just need that output to create a string text that says: "Hey, you changed Obj2 to Obj2-updated". But all I need is just to know which property was modified. – Valip Aug 22 '16 at 08:55
  • @NinaScholz it doesn't matter if the output is a string or an object. – Valip Aug 22 '16 at 08:57
  • 1
    I'm voting to close this question because it's a continually moving target for those trying to answer. Before asking a question take some time to first work out what exactly you want. Check that the input you post is accurate (an Array of Objects, not simply two different Objects, to compare), and that you know what result you need, whether it's the changed-value, the changed-value *and* the key of that value, or the whole Object with the changed-value; ten minutes would have saved time for all. – David Thomas Aug 22 '16 at 11:17

5 Answers5

15

You could filter the keys and get a result set with the updated keys.

var orig = [{ enabled: "true", name: "Obj1", id: 3 }, { enabled: "true", name: "Obj2", id: 4 }],
    update = [{ enabled: "true", name: "Obj1", id: 3 }, { enabled: "true", name: "Obj2-updated", id: 4 }],
    difference = [];

orig.forEach(function (a, i) {
    Object.keys(a).forEach(function (k) {
        if (a[k] !== update[i][k]) {
            difference.push({ id: update[i].id, key: k, value: update[i][k], index: i });
        }
    });
});

console.log(difference);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Can you please tell me if there is a way to log the modified object? In this case `{ enabled: "true", name: "Obj2-updated", id: 4 }` – Valip Aug 22 '16 at 09:41
  • 8
    And you see, this is why [I asked you, earlier, if you're sure you only needed the changed value](http://stackoverflow.com/questions/39074429/how-to-find-differences-between-two-javascript-arrays-of-objects#comment65497981_39074429). So far the question has changed, and the required return values have changed, from just the changed value, to the changed-value *and* the key for that value and *now* you've decided that you want the whole of the modified object to be returned. Please, take five minutes *before* asking a question to properly compose the question. – David Thomas Aug 22 '16 at 09:44
  • 1
    @PavelValeriu, if i would know, **how** the result should look like, i could give an answer. so what do you need? the object, or an index or the key/value pair or what? – Nina Scholz Aug 22 '16 at 09:54
  • @NinaScholz it would be ideal for me if I can output a message like `var 4 -> modified name to Obj2-updated`...I assume that it is a combination between `ES5 (the "classic style")` and `temptation` – Valip Aug 22 '16 at 10:31
  • Is it possible to output both the value of `id` property and the modified value? – Valip Aug 22 '16 at 10:55
  • 2
    @PavelValeriu: Of course it's possible. Just look closely at what Nina's solution is doing, follow it step-by-step in the debugger, and you'll be able to work out how to do that. – T.J. Crowder Aug 22 '16 at 16:46
6

Assuming, that the property names of both are identical and the values are just primitives (no objects, arrays etc.):

Object.keys( orig )
      .forEach( (key) => {
        if( orig[ key ] !== update[ key ] ) {
          console.log( update[key] );
        }
      });
Sirko
  • 72,589
  • 19
  • 149
  • 183
  • Can I use `orig[prop][key]` ? – Valip Aug 22 '16 at 08:23
  • @PavelValeriu To do what? In your example code, you assume, that both variables contain arrays, but they are objects actually. So your `.length` actually should not work (unless you set it somewhere explicitly) – Sirko Aug 22 '16 at 08:24
  • It's not worth my posting a separate answer, given that it's essentially the same, but since the OP only wants to know which values are different (without reference to the keys, apparently) it's a little easier to use [`Object.values()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/values), rather than accessing the values of the Object via the keys on each iteration (this does require that `Object.values()` is implemented in the browser though, obviously). – David Thomas Aug 22 '16 at 08:30
  • @DavidThomas Out of curiosity: How would you match the values to each other using `Object.values()` without having access to the respective keys? – Sirko Aug 22 '16 at 08:34
  • @Sirko sorry, my `orig` and `update` are arrays that contain objects, I will update my question – Valip Aug 22 '16 at 08:35
  • @PavelValeriu The new question just adds a new dimension to the problem: first map all objects considered equal to one another and then use one of the answers' code to compare them. – Sirko Aug 22 '16 at 08:40
  • Having written it I have to retract my comment; using `Object.keys()` is the better approach (for a few reasons), however: this is how I implemented your solution using `Object.values()`: https://jsfiddle.net/t14w0r1z/ – David Thomas Aug 22 '16 at 08:48
3

Use Object.keys to cycle through your object. Something like:

var orig = {
  enabled: "true",
  name: "Obj1",
  id: 3
};

var update = {
  enabled: "true",
  name: "Obj1-updated",
  id: 3
};

var diff = {};

Object.keys(orig).forEach(function(key) {
  if (orig[key] != update[key]) {
    diff[key] = update[key];
  };
})

console.log(diff);
tewathia
  • 6,890
  • 3
  • 22
  • 27
3

You can use a single loop to go through the properties of the original object and check against the updated object to find out which properties have been modified.

var orig = {
  enabled: "true",
  name: "Obj1",
  id: 3
};

var update = {
  enabled: "true",
  name: "Obj1-updated",
  id: 3
};

for (var key in orig) {
  if (orig[key] !== update[key]) {
    console.log(key + ': ' + update[key]);
  }
}
Abdul Mateen Mohammed
  • 1,864
  • 1
  • 12
  • 21
0

You could use a library like lodash or Ramda to do it in a concise manner. In the case of Ramda you could do: R.difference(update, orig);

Barry G
  • 221
  • 4
  • 14