Nas Nas - 15 days ago 5
Javascript Question

using underscore's “difference” method on objects

_.difference([], [])


this method works fine when i'm having primitive type data like

var a = [1,2,3,4];
var b = [2,5,6];


and the
_.difference(a,b)
call returns
[1,3,4]


but in case i'm using object like

var a = [{'id':1, 'value':10}, {'id':2, 'value':20}];
var b = [{'id':1, 'value':10}, {'id':4, 'value':40}];


doesn't seem to work

Answer

Reason is simply that object with same content are not same objects e.g.

var a = [{'id':1, 'value':10}, {'id':2, 'value':20}]; 
a.indexOf({'id':1, 'value':10})

It will not return 0 but -1 because we are searching for a different object

See the source code http://underscorejs.org/underscore.js, _.difference uses _.contains

_.difference = function(array) {
  var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
  return _.filter(array, function(value){ return !_.contains(rest, value); });
};

and _.contains ultimately uses indexOf hence will not find objects unless they point to same object.

You can improve the underscore _.contains by looping through all items and calling a compare callback, which you should be able to pass to difference or contains function or you can check this version which improves contains methods

Comments