Reputation: 6363
I have 2 arrays, one is newVal and the other is origVal define
orig:
[
{"ListingId":1762276,"Rating":3,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
]
new:
[
{"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
]
If I change one of the ratings in new, how might I detect that change, and retrieve the changed object?
There will only be one change at a time, although I don't think that matters.
FYI: These arrays are being produced from an Anjularjs watchcollection
$scope.$watchCollection('items', function (new, old) {
}, true);
Thank you, Stephen
Upvotes: 10
Views: 15055
Reputation: 4485
Building on @Jonathan's answer, I have tweaked a version that returns a usable list of differences including which side had diff and the index of the record.
var a = [
{"ListingId":1762276,"Rating":3,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
];
var b = [
{"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832131,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
]
function diff(arr1, arr2){
var aDiffs=[]
function __comp(arrL, arrR, side){
var rL, rR, bFound
for(var i=0;i<arrL.length;i++){rL=arrL[i]
bFound=false
for(var j=0;j<arrR.length;j++){rR=arrR[j]
if (_.isEqual(rL, rR)){
bFound=true
break
}
}
if (!bFound)aDiffs.push({side: side, ind: i, obj: rL})
}
}
__comp(arr1, arr2, 'l')
__comp(arr2, arr1, 'r')
return aDiffs
};
console.log(JSON.stringify(diff(b, a)).replace(/},{/g, "}\n,{"));
Output:
[{"side":"l","ind":0,"obj":{"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"}}
,{"side":"l","ind":3,"obj":{"ListingId":1832131,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"}}
,{"side":"r","ind":0,"obj":{"ListingId":1762276,"Rating":3,"ListPrice":7411828,"PropertyType":"Residential"}}
,{"side":"r","ind":3,"obj":{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"}}]
Upvotes: 1
Reputation: 131
How about:
const current = [{name:'a'},{name:'b'},{name:'c'}]
const update = [{name:'x'},{name:'a'},{name:'b'},{name:'f'}]
const records = current.concat(update);
const diff = {};
diff.in = []
diff.out = [];
records.forEach(item => {
if(!current.find(cur => item.name == cur.name))diff.in.push(item)
if(!update.find(up => item.name == up.name ))diff.out.push(item)
})
Upvotes: 0
Reputation: 14766
Take a look to this:
var a = [
{"ListingId":1762276,"Rating":3,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
];
var b = [
{"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"},
{"ListingId":1826692,"Rating":3,"ListPrice":650000,"PropertyType":"Residential"},
{"ListingId":1833283,"Rating":4,"ListPrice":950000,"PropertyType":"Residential"},
{"ListingId":1832134,"Rating":3,"ListPrice":850000,"PropertyType":"Residential"},
{"ListingId":1829932,"Rating":4,"ListPrice":750000,"PropertyType":"Residential"},
{"ListingId":1827548,"Rating":5,"ListPrice":650000,"PropertyType":"Residential"}
]
var difference = function(array){
var rest = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
var containsEquals = function(obj, target) {
if (obj == null) return false;
return _.any(obj, function(value) {
return _.isEqual(value, target);
});
};
return _.filter(array, function(value){ return ! containsEquals(rest, value); });
};
console.log(JSON.stringify(difference(b, a)));
> [{"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"}]
The code is based on the original function difference from underscore, but it performs a deep comparison between objects using isEqual.
Upvotes: 12
Reputation: 664405
If the order does not change, a simple iteration will do it. Underscore provides the find
method for this task:
var changedObj = _.find(newVal, function(obj, index) {
return obj.Rating != oldVal[index].Rating;
});
Upvotes: 4