Reputation: 300
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
Upvotes: 0
Views: 159
Reputation: 4198
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:
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.
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"}}
]
A
rray value of 307
at index 0
: 45467
has been D
eletedA
rray value of 307
at index 1
: 45468
has been D
eletedA
rray value of 355
at index 1
: 45467
has been N
ewly addedUpvotes: 0
Reputation: 386550
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);
Upvotes: 0
Reputation: 5075
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);
Upvotes: 1