67

What's the fastest/best way to compare two arrays and return the difference? Much like array_diff in PHP. Is there an easy function or am I going to have to create one via each()? or a foreach loop?

Rahil Wazir
  • 10,007
  • 11
  • 42
  • 64
Howdy_McGee
  • 10,422
  • 29
  • 111
  • 186
  • Hiya man, I reckon you can use `inArray` and populate the difference between 2 Arrays; I have pasted a working demo for you, hope it helps B-) – Tats_innit Jun 07 '12 at 08:15
  • duplicate of http://stackoverflow.com/questions/1187518/javascript-array-difference (even if it was already linked elsewhere in there, somewhere) – cregox May 14 '15 at 18:45
  • You probably want [this answer from a past SO question](http://stackoverflow.com/a/4026828/304588). It builds on the Array prototype. – Richard Neil Ilagan Jun 07 '12 at 07:48

10 Answers10

147

I know this is an old question, but I thought I would share this little trick.

var diff = $(old_array).not(new_array).get();

diff now contains what was in old_array that is not in new_array

superphonic
  • 7,954
  • 6
  • 30
  • 63
  • 2
    short and sweet.. just like i like it.. i used that with `$.merge()` to concatenate differences in specific a specific order... – kingkode Oct 09 '13 at 17:17
  • 1
    will this work if the array contains objects? I'm trying to compare objects within two arrays – Batman Jan 19 '14 at 06:53
  • 2
    Here is a scenario. This works fine for `$(['h','h','h','h','h']).not($(["a", "a", "a"]))` but for an array like `$(['h','h','h','h','h']).not($(["a", "a", "a", "h"]))` (NOTICE the last "h" in the array) it returns an empty array. The difference is not returned. Hence, it is faulty. – Vishnu Narang Feb 06 '14 at 07:18
  • 2
    @VishnuNarang I think you are misunderstanding a few things here. Firstly how array differencing works, and secondly not reading the actual question the OP asked. Lets deal with the first misunderstanding. Returning an empty array in your second example is EXACTLY the right result. It is returning what was in the first array, that is not in the second (i.e nothing). This is the "difference" between the first array and the second. Secondly, the OP asked for a jQuery Function like PHP's (array_diff). This is it! Your example run through PHP's array_diff() function produces an empty array as well – superphonic Feb 06 '14 at 10:50
  • @VishnuNarang I am pretty confident that PHP's array_diff() function is not faulty. – superphonic Feb 06 '14 at 10:51
  • Firstly i did not answer the asked question. I merely commented on this answer indicating what Jquery does. And using `.not` to get the different is probably not the best way to do it because it does not give the difference in the real sense. It just does what you rightly explained. So the point is, `.not` is not the same as difference between the two arrays. My example clearly says that the arrays are different but the return value is empty. Hence, i rest my case with that. Anyways, thanks. – Vishnu Narang Feb 06 '14 at 12:02
  • Oh FYI, the code i'm working on had the `.not` implementation and in the process of solving a production bug, i discovered it was used for a scenario which cannot be solved using `.not`. Hence, if you want the difference between two arrays, i would rather suggest to use something more robust. Ofcourse that depends of the needs too. Thanks again. – Vishnu Narang Feb 06 '14 at 12:06
  • @VishnuNarang Unfortunately I do not really understand what it is your are trying to do, or what you mean by `does not give the difference in the real sense`?. I think you may be talking about a "Symmetric Difference" which this solution isn't and the OP didn't ask for. It is however the correct answer to this question, and is definitely NOT faulty, as you said in your original comment. – superphonic Feb 06 '14 at 14:42
  • @superphonic is there a doc that talks about using jQuery with non-elements? Like here you used it with an array, but I don't see any docs about it. – Jayen Jul 27 '14 at 05:43
  • @Jayen Not that I know of... When you use a regular array with `.not()`, jQuery actually uses it's built-in utility `.grep()` which is specifically for manipulating arrays. jQuery has lots of utilities that do not deal with elements, you can see the full list here http://api.jquery.com/category/utilities/ – superphonic Jul 28 '14 at 11:48
  • jQuery `not` no longer works with generic objects as of 3.0.0-rc1. See https://github.com/jquery/jquery/issues/3147 – Marc-André Lafortune Jun 09 '16 at 15:39
  • So clean - wish JS core had a diff func like php! – hot_barbara Feb 21 '19 at 22:18
71

Working demo http://jsfiddle.net/u9xES/

Good link (Jquery Documentation): http://docs.jquery.com/Main_Page {you can search or read APIs here}

Hope this will help you if you are looking to do it in JQuery.

The alert in the end prompts the array of uncommon element Array i.e. difference between 2 array.

Please lemme know if I missed anything, cheers!

Code

var array1 = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var difference = [];

jQuery.grep(array2, function(el) {
        if (jQuery.inArray(el, array1) == -1) difference.push(el);
});

alert(" the difference is " + difference);​ // Changed variable name 
user4035
  • 22,508
  • 11
  • 59
  • 94
Tats_innit
  • 33,991
  • 10
  • 71
  • 77
9

use underscore as :

_.difference(array1,array2)
anurag_29
  • 922
  • 10
  • 19
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – AlSki Feb 27 '14 at 14:22
  • 2
    @AlSki it gives the answer to the question asked! compares the two arrays and returns the diff. – anurag_29 Feb 28 '14 at 13:31
  • 1
    @anurag_29 The question was how to do it with jQuery, not underscore. – reergymerej Mar 31 '15 at 20:46
  • 1
    @AlSki When the answer is being posted YEARS later, t's appropriate, I think, to post an answer that involves the use of a different library than the question asked about, because that is a possible answer to the question - not knowing one way or the other if the OP, or others visiting the question years later, are aware of the library. – Dan Nissenbaum Jun 25 '15 at 04:55
3
var arrayDiff = function (firstArr, secondArr) {
    var i, o = [], fLen = firstArr.length, sLen = secondArr.length, len;


    if (fLen > sLen) {
        len = sLen;
    } else if (fLen < sLen) {
        len = fLen;
    } else {
        len = sLen;
    }
    for (i=0; i < len; i++) {
        if (firstArr[i] !== secondArr[i]) {
            o.push({idx: i, elem1: firstArr[i], elem2: secondArr[i]});  //idx: array index
        }
    }

    if (fLen > sLen) {  // first > second
        for (i=sLen; i< fLen; i++) {
            o.push({idx: i, 0: firstArr[i], 1: undefined});
        }
    } else if (fLen < sLen) {
        for (i=fLen; i< sLen; i++) {
            o.push({idx: i, 0: undefined, 1: secondArr[i]});
        }
    }    

    return o;
};
3
/** SUBTRACT ARRAYS **/
function subtractarrays(array1, array2){
    var difference = [];
    for( var i = 0; i < array1.length; i++ ) {
        if( $.inArray( array1[i], array2 ) == -1 ) {
                    difference.push(array1[i]);
        }
    }

    return difference;
}   

You can then call the function anywhere in your code.

var I_like    = ["love", "sex", "food"];
var she_likes = ["love", "food"];

alert( "what I like and she does't like is: " + subtractarrays( I_like, she_likes ) ); //returns "Naughty"!

This works in all cases and avoids the problems in the methods above. Hope that helps!

Howdy_McGee
  • 10,422
  • 29
  • 111
  • 186
Kareem
  • 5,068
  • 44
  • 38
3

The short version can be like this:

const diff = (a, b) => b.filter((i) => a.indexOf(i) === -1);

result:

diff(['a', 'b'], ['a', 'b', 'c', 'd']);

["c", "d"]
Maksym Kalin
  • 1,693
  • 16
  • 18
2

if you also want to compare the order of the answer you can extend the answer to something like this:

Array.prototype.compareTo = function (array2){
    var array1 = this;
    var difference = [];
    $.grep(array2, function(el) {
        if ($.inArray(el, array1) == -1) difference.push(el);
    });
    if( difference.length === 0 ){
        var $i = 0;
        while($i < array1.length){
            if(array1[$i] !== array2[$i]){
                return false;
            }
            $i++;
        }
        return true;
    }
    return false;
}
Dries
  • 400
  • 5
  • 22
2

In this way you don't need to worry about if the first array is smaller than the second one.

var arr1 = [1, 2, 3, 4, 5, 6,10],
    arr2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];

function array_diff(array1, array2){
    var difference = $.grep(array1, function(el) { return $.inArray(el,array2) < 0});
    return difference.concat($.grep(array2, function(el) { return $.inArray(el,array1) < 0}));;
}

console.log(array_diff(arr1, arr2));
Behnam Rasooli
  • 712
  • 5
  • 20
1

Array operations like this is not jQuery's strongest point. You should consider a library such as Underscorejs, specifically the difference function.

Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46
1

This should work with unsorted arrays, double values and different orders and length, while giving you the filtered values form array1, array2, or both.

function arrayDiff(arr1, arr2) {
    var diff = {};

    diff.arr1 = arr1.filter(function(value) {
        if (arr2.indexOf(value) === -1) {
            return value;
        }
    });

    diff.arr2 = arr2.filter(function(value) {
        if (arr1.indexOf(value) === -1) {
            return value;
        }
    });

    diff.concat = diff.arr1.concat(diff.arr2);

    return diff;
};

var firstArray = [1,2,3,4];
var secondArray = [4,6,1,4];

console.log( arrayDiff(firstArray, secondArray) );
console.log( arrayDiff(firstArray, secondArray).arr1 );
// => [ 2, 3 ]
console.log( arrayDiff(firstArray, secondArray).concat );
// => [ 2, 3, 6 ]
Elvis
  • 289
  • 4
  • 14