How can I check if arrays are equal in javascript?

24,418

Solution 1

JavaScript array comparisons like you've written are just simple object reference comparisons. They're not "deep" comparisons element by element.

You can write your own comparison function, something to check that the lengths are the same and the the elements are the same, either in order or not, as fits your needs. edit As others point out, there are several libraries that include array comparison functions. If you find one that meets your definition of "equality" (not unlikely), and you don't mind considering incorporating that library into your architecture, that might be a good idea.

Solution 2

You can use the Underscore.js library's isEqual method.

http://underscorejs.org/#isEqual

Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.

var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
moe == clone;
=> false
_.isEqual(moe, clone);
=> true

UPDATE

Lodash is inspired by underscore, but nowadays is superior solution

https://lodash.com/docs/#isEqual

Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.

var object = { 'a': 1 };
var other = { 'a': 1 };

_.isEqual(object, other);
// => true

object === other;
// => false

Solution 3

Use lodash.

_.isEqual([1,2],[1,2])

Also works with objects.

_.isEqual({a:1}, {a:1})

Solution 4

Arrays are Objects in javascript. And comparing objects can’t be done using == like you would normally use when comparing strings or numbers.

There are many other ways to compare arrays, my favourite is using JSON:

if ( JSON.stringify(a) == JSON.stringify(b) ) {
    // equal

Note that assigning a pre-existing object to a variable like you do when you write b = a is just copying a reference. They both point to the same array.

You would have to do b = a.slice() to get a real copy.

Share:
24,418
Shawn
Author by

Shawn

I learned about the web by myself thanks to free and open-source software and the original spirit of the Internet. I am thankful for having found the web for it gave me a path towards learning that school couldn't offer and eventually a long and interesting career. To keep things fresh, I have recently started pivoting towards consulting and mentorship. I guess I need to see more people and fewer computers.

Updated on October 19, 2020

Comments

  • Shawn
    Shawn over 3 years

    Have a look at this code sample or go to the jsfiddle

    function printRelation(a, b, out) {
        var text;
        if (a === b) {
            text = "a === b";
        } else if (a == b) {
            text = "a == b";
        } else {
            text = "a != b";
        }
        $('#' + out).text(text);
    }
    
    var a = [0, 0, 2], b = a;
    printRelation(a, b, 'out1');
    a = [0, 0, 2];
    b = [0, 0, 2];
    printRelation(a, b, 'out2');
    

    I would have expected both tests to output a === b, but only the first one does. The second one outputs a != b. Can anyone explain this behaviour? How can I efficiently compare arrays in javascript?

    • JConstantine
      JConstantine over 11 years
    • Thomas
      Thomas over 11 years
      I guess the === operator compares arrays by reference, which would explain the observed behaviour. EDIT: Answered by Pointy in the meantime.
  • MarioDS
    MarioDS over 11 years
    And don't forget to do the reference check first too, in the custom function.
  • Pointy
    Pointy over 11 years
    @MarioDeSchaepmeester ah yes that's a good idea! No use doing extra work if the two arrays are really the same array!
  • Prinzhorn
    Prinzhorn over 11 years
    Nice idea. Works for usual cases but not general purpose.
  • Thomas
    Thomas over 11 years
    Nice solution! +1... It also works with objects, but be careful: var a = {a:0, b:0, c:2}; var b = {c:2, b:0, a:0}; would result "false".
  • Stefan Kendall
    Stefan Kendall over 11 years
    "Write your own." Christ. No.
  • David Hellsing
    David Hellsing over 11 years
    @Thomas true, they need to have the same "order" to equal so it’s mostly for arrays I guess.
  • I Hate Lazy
    I Hate Lazy over 11 years
    JSON.stringify'ing the arrays has other limitations as well since JSON supports only a subset of the value types supported in JavaScript. I personally think it's overkill to create JSON strings, especially considering its serious limitations.
  • I Hate Lazy
    I Hate Lazy over 11 years
    @StefanKendall: Why would we be afraid of writing a little reusable code that suits our specific needs?
  • Pointy
    Pointy over 11 years
    @StefanKendall that reflects a limited view of reality there. For all we know, the OP may consider two arrays to be "equal" if they contain the same elements, but not necessarily in the same order. Perhaps they're equal if a string "17" in one array can match a numeric 17 in the other. The point is that the meaning of "equal" is not necessarily always the same. If a library is already in use that contains some generic array equality test, then of course it would be foolish not to use it.
  • Pointy
    Pointy over 11 years
    @Thomas not necessarily; strictly speaking the behavior is really not well-defined for objects, as JavaScript does not specify the order of property iteration in for ... in loops. Of course it can generally be relied upon, but it's a little worrisome to do so from a formal standpoint.
  • Stefan Kendall
    Stefan Kendall over 11 years
    @user1689607: Because it's not re-usable, you probably didn't write tests or documentation for it, and 3 years from now, I'm going to inherit your project and lose 3 days trying to figure out why my client's site can't make sales.
  • Stefan Kendall
    Stefan Kendall over 11 years
    @Pointy: Tests/Code define expected behavior, and there are libraries mentioned which pass the original post's criteria of equal. "Write your own implementation" is a bad gut reaction that leads to code bloat, bugs, and a precedent for duplicating existing functionality.
  • Pointy
    Pointy over 11 years
    @StefanKendall well an argument could be made that importing Underscore solely to access the array equality comparator would be some "bloat" :-) The assumption that a private implementation would not be re-usable nor be tested is also pretty presumptive. There are good things and bad things about relying on external libraries. The answer has been amended in any case.
  • Stefan Kendall
    Stefan Kendall over 11 years
    @Pointy: I've run into private implementations of arrayEquals several times. They were all untested and undocumented, and even the ones that were tested required re-learning, versus a library that many people are already familiar with, such as underscore. Underscore is insignificantly small in almost all circumstances. Why is my home-rolled version of async.js worse than async.js? Because nobody has ever used my home-rolled version but me and those on my team. Ergo private implementations suck by default.
  • Pointy
    Pointy over 11 years
    @StefanKendall I appreciate your clearly explained opinions about this. I do a lot of work in relative isolation, so ideas that challenge my subconscious inclinations are always refreshing.
  • Jon z
    Jon z almost 9 years
    note that order matters in an array, so _.isEqual([1, 2, 3], [3, 2, 1]) => false
  • Stefan Kendall
    Stefan Kendall over 8 years
    var a= [{a:1,b:2}]; var b = [{b:2,a:1}]; JSON.stringify(a) === JSON.stringify(b) -> false. This answer is wrong.
  • ersefuril
    ersefuril almost 8 years
    Just wanted to say : this is working great for checking [1, 2] with [1, 2], but not for checking [1, 2] with [2, 1] (lodash check if order is the same).