10

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

3
  • Are those the same objects in the array (i.e. === identity) or are they only similar-looking? Commented Aug 22, 2013 at 14:47
  • What result do you need? The index of the changed object in the array, the new changed object, the old changed object, the rating? Commented Aug 22, 2013 at 14:48
  • I would prefer the changed object ie {"ListingId":1762276,"Rating":2,"ListPrice":7411828,"PropertyType":"Residential"} Commented Aug 22, 2013 at 14:50

4 Answers 4

12

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.

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

1 Comment

It's brilliant, what it does. I wish I could understand the code.
4

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;
});

Comments

1

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"}}]

Comments

0

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)
})

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.