0

Array 1 is the result of the data from a localstorage

Array 2 is, for the same IDs (329, 307, 355), the result after treatment

So i need to compare both to notify what changed

Array 1 :

[{"329":["45738","45737","45736"]},{"307":["45467","45468"]},{"355":["47921"]}]

Array 2 :

[{"355":["47921","45922"]},{"329":["45738","45737","45736"]},{"307":[]}]

I need to compare Array 2 with Array 1 and extract differences.

In this example i want to have for result

[{"355":["45922"]},{"307":[]}]

I try to adapt this code :

var compareJSON = function(obj1, obj2) {
  var ret = {};
  for(var i in obj2) {
    if(!obj1.hasOwnProperty(i) || obj2[i] !== obj1[i]) {
      ret[i] = obj2[i];
    }
  }
  return ret;
};

Runnable:

var array1 = [{
    "329": ["45738", "45737", "45736"]
  }, {
    "307": ["45467", "45468"]
  }, {
    "355": ["47921"]
  }],
  array2 = [{
    "355": ["47921", "45922"]
  }, {
    "329": ["45738", "45737", "45736"]
  }, {
    "307": []
  }]

var compareJSON = function(obj1, obj2) {
  var ret = {};
  for (var i in obj2) {
    if (!obj1.hasOwnProperty(i) || obj2[i] !== obj1[i]) {
      ret[i] = obj2[i];
    }
  }
  return ret;
};

console.log(compareJSON(array1, array2));

But, either I have nothing or I have the whole table

15
  • 4
    why are in the result in 307 no items? Commented May 2, 2017 at 18:42
  • 1
    Can you clarify what you mean by "extract differences"? I'm not sure exactly what rules produced the result for your example. Commented May 2, 2017 at 18:43
  • 1
    I'm voting to close this question as too broad because the code would likely need to be modified significantly in order to achieve the expected results Commented May 2, 2017 at 18:47
  • obj2[i] !== obj1[i] is comparing arrays. Note that in Javascript: [] !== []. So that test is probably returning false all the time. Commented May 2, 2017 at 18:50
  • 2
    ^^^ it's not an answer, why is 307 included in the result with an empty array? Commented May 2, 2017 at 18:55

3 Answers 3

1

your requirement(result) is not clear, but this will get you started.

var arr1 = [{ "329": ["45738", "45737", "45736"] }, { "307": ["45467", "45468"] }, { "355": ["47921"] }],
  arr2 = [{ "355": ["47921", "45922"] }, { "329": ["45738", "45737", "45736"] }, { "307": [] }];

var result = [];

arr2.forEach(obj => {
  var key = Object.keys(obj)[0];
  var match = arr1.find(o => o.hasOwnProperty(key));
  if (match) {
    var newObj = {};
    newObj[key] = obj[key].filter(s => match[key].indexOf(s) === -1);
    if (!obj[key].length || newObj[key].length) result.push(newObj)
  } else {
    result.push(Object.assign({}, obj));
  }
});

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

Just before the end of forEach i need to update arr1 with data of arr2. So when i reload, newObj is reset to 0 (so, no differences yet). But is there a way to store differences in a variable, and concatenate it every time there are new differences ? I try to push in an array but it overwrites it
0

You could use a hash tbale and delete found items. If some items remains, then an empty array is taken to the result object.

var array1 = [{ 329: ["45738", "45737", "45736"] }, { 307: ["45467", "45468"] }, { 355: ["47921"] }],
    array2 = [{ 355: ["47921", "45922"] }, { 329: ["45738", "45737", "45736"] }, { 307: [] }],
    hash = {},
    result = [];

array1.forEach(function (o) {
    Object.keys(o).forEach(function (k) {
        hash[k] = hash[k] || {};
        o[k].forEach(function (a) {
            hash[k][a] = true;
        });
    });
});

array2.forEach(function (o) {
    var tempObject = {};
    Object.keys(o).forEach(function (k) {
        var tempArray = [];
        o[k].forEach(function (a) {
            if (hash[k][a]) {
                delete hash[k][a];
            } else {
                tempArray.push(a);
            }
        });
        if (tempArray.length || Object.keys(hash[k]).length) {
            tempObject[k] = tempArray;
        }
    });
    Object.keys(tempObject).length && result.push(tempObject);
});

console.log(result);

Comments

0

I've used the deep-diff package in npm for this sort of thing before:

It may be more detail than you want though - here's an example from the readme of the output format:

[ { kind: 'E',
  path: [ 'name' ],
  lhs: 'my object',
  rhs: 'updated object' },
{ kind: 'E',
  path: [ 'details', 'with', 2 ],
    lhs: 'elements',
    rhs: 'more' },
{ kind: 'A',
  path: [ 'details', 'with' ],
  index: 3,
  item: { kind: 'N', rhs: 'elements' } },
{ kind: 'A',
  path: [ 'details', 'with' ],
  index: 4,
  item: { kind: 'N', rhs: { than: 'before' } } } ]

Checkout the readme on the github page linked above for details about what it all means, or try it out for yourself online using runkit

But in order for this to work you would have to do some sort of preprocessing:

Sort array based on first key of each element:

a1 = a1.sort((lhs, rhs) => {
  return parseInt(Object.keys(lhs)[0]) - parseInt(Object.keys(rhs)[0]);
})

If you sort both of the arrays by the first key of each element and then pass it to the diff tool, you get the following:

[
  {"kind":"A","path":[0,"307"],"index":0,"item":{"kind":"D","lhs":"45467"}},
  {"kind":"A","path":[0,"307"],"index":1,"item":{"kind":"D","lhs":"45468"}},
  {"kind":"A","path":[2,"355"],"index":1,"item":{"kind":"N","rhs":"45922"}}
]

If it were me I would probably merge all the array elements and diff the resulting object so you completely avoid any object order and duplicate key issues.

Alternative: merge array contents into one object

A naive merge might look like this:

a1Object = {}

a1.forEach((element) => { 
    Object.keys(element).forEach((key) => {
        a1Object[key] = element[key];
    });
})

Which produces the following diff:

[
  {"kind":"A","path":["307"],"index":0,"item":{"kind":"D","lhs":"45467"}},
  {"kind":"A","path":["307"],"index":1,"item":{"kind":"D","lhs":"45468"}},
  {"kind":"A","path":["355"],"index":1,"item":{"kind":"N","rhs":"45922"}}
]

Interpreting the diff output

  • there is a change in the Array value of 307 at index 0: 45467 has been Deleted
  • there is a change in the Array value of 307 at index 1: 45468 has been Deleted
  • there is a change in the Array value of 355 at index 1: 45467 has been Newly added

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.