using underscore's “difference” method on arrays of 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



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, _.difference uses _.contains

_.difference = function(array) {
  var rest = concat.apply(ArrayProto,, 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


try this on for size for finding the difference of an array of objects:

var test = [{a: 1},{b: 2}];
var test2 = [{a: 1}];

_.filter(test, function(obj){ return !_.findWhere(test2, obj); });

I actually can imagine situations where I'd rather use @kontr0l approach than something else, but you have to understand that this approach is quadratic, so basically this code is an abstraction for naïve approach - iterate through all values in two arrays.

There are approaches better than quadratic, I won't use here any big O notation, but here are two main approaches, both are better then naïve one:

  • iterate through one of the arrays and check for existence in sorted second array using binary search.
  • put values into set/hash/dictionary/you name it.

As it've been already mentioned, first approach can be adopted for objects if you reimplement standard difference method with using some more flexible analogue of indexOf method.

With second approach we can hit the wall with the fact that, as of Feb'2015, only modern browsers are supporting Sets. As of hashes (well, objects) in javascript, they can have only string-type keys, so any object invoked as key first shoud be converted via toString method. So, we need to provide some => correspondece. On practice in most cases it's pretty straightforward, for instance, for your particular example such correspondence can be just String(

Having such correspondence, we also can use following lodas/undercore approach:

var idsA = _.pluck(a, 'id');
var idsB = _.pluck(b, 'id');

// actually here we can stop in some cases, because 
// quite often we need to identify object, but not the object itself - 
// for instance to send some ids through remote API.
var intersect = _.intersection(idsA, idsB);

//to be 100% sure you get the idea, here we assume that object having equal ids are treated as equal, so does not really matter which of arrays we'll iterate:

var dictA = _.object(idsA, a); // now we can find a by id faster then with _.find
var intersectObj = {return dictA[id})

But buy admitting slightly stricter restriction - that we can build correspondence between our set objects and natural numbers we can build even more efficent algorithm, i.e. all our ids are non-negative integers - we can use more efficient algorithm.

The trick is to implement set by introducing two helper arrays this way:

var naturalSet = function (arr) {
    var sparse = [];
    var dense = [];

    var contains = function (i) {
        var res = sparse[i] < dense.length && dense[sparse[i]] == i;
        return res;

    var add = function (v) {
        if (!contains(v)) {
            sparse[v] = dense.length;


    return {
        contains: contains,
        toArray: function () {
            return dense
        _getDense: function () {
            return dense
        _getSparse: function () {
            return sparse

Then we can introduce set with mapping to naturalSet:

var set = function (arr, valueOf) {
    var natSet = naturalSet(;
    return {
        contains: function (item) {
            return natSet.contains(valueOf(item))
        toArray: function () {
            var sparse = natSet._getSparse();
            var res = natSet._getDense().map(function (i) {
                return arr[sparse[i]];
            return res;

and finally, we can introduce intersection:

var intersection = function(arr1, arr2, valueOf) {
   return set(arr2.filter(set(arr1, valueOf).contains), valueOf).toArray();

So, relying on the structure of data you are working can help you sometimes.

without using underscorejs,
here is the pretty simple method i got solution ... 

a = [{'key':'123'},{'key':'222'},{'key':'333'}]
b = [{'key':'123'},{'key':'222'}]

var diff = a.filter(function(item1) {
  for (var i in b) {
    if (item1.key === b[i].key) { return false; }
  return true;

Forgive me for hopping in late here, but this may help:

array_of_objects = 
    // return the non-matching items (without the expected properties)
        // filter original list for items with expected properties
            // original list
            // expected properties
            {'id':1, 'value':10}

Don't get why these answers are so complex unless I'm missing something?

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

// Or use lodash _.differenceBy
const difference = (array1, array2, prop = 'id') =>
  array1.filter(item1 =>
    !array2.some(item2 =>
      item2[prop] === item1[prop],
// In one array.
console.log(difference(a, b));

// Intersection.
console.log([...difference(a, b), ...difference(b, a)]);


While the accepted answer is correct, and the other answers give good ideas as well, there is an additional option that's pretty easy to implement with underscore.

This solution relies on each object having a unique ID, but in many cases this will be true, and you can get the difference of two arrays of objects in just two lines of code.

Using underscore's "pluck" method, you can quickly construct an array of all of the ID's in your source set and the target set. From there, all of underscore's array methods will work, difference, union, intersection etc...

After the operation, it is trivial to obtain the list of objects from your source list that you desire. Here's an example:


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

var arr1 = _.pluck(a, "id");
var arr2 = _.pluck(b, "id");
var diff = _.difference(arr1, arr2);
var result = _.filter(a, function(obj) { return diff.indexOf( >= 0; });

or, more concisely:

var diff = _.difference(_.pluck(a, "id"), _.pluck(b, "id"));
var result = _.filter(a, function(obj) { return diff.indexOf( >= 0; });

Of course, this same technique can be extended for use with any of the array methods.

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

var c = _.difference( =>, =>;
var array = [];
array = => {
     return e;


Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.