30

I'm trying to compare two arrays in javascript.

What I'd like is:

a < b &iff; ∃ i ≥ 0 s.t. a[i] < b[i] and ∀ 0 ≤ j < i, a[j] = b[j]

So arrays of non-negative numbers work as desired:

firebug> [0,1,2,3,4] < [1,0,0]
true

And comparing negative numbers with zero works as expected:

firebug> [-1, 1] < [0, 0]
true

But comparing negative numbers with negative numbers is... suprising:

firebug> [-2] < [-1]
false
firebug> -2 < -1
true

What's going on here, so I can correct my intuition for what array comparison means in javascript?

rampion
  • 87,131
  • 49
  • 199
  • 315
  • See also [How are arrays compared in JavaScript](http://stackoverflow.com/q/16566772/1048572) for an explanation of the behaviour and [Three-way compare function for Arrays in Javascript](http://stackoverflow.com/q/23881838/1048572) for a solution – Bergi Feb 11 '16 at 00:59
  • Specification is here: [abstract operation IsLessThan](//tc39.es/ecma262/#sec-islessthan). – Sebastian Simon Sep 23 '21 at 19:05

3 Answers3

34

The array is converted to a string, which comes down to .join(), which in turn joins the elements with a comma (,) as delimiter.

"-1,1" < "0,0" === true

because the character code of - (45) is smaller than the character code of 0 (48).

On the other hand,

"-2" < "-1" === false

because the second character codes are compared (the first are both -, so that doesn't give a result yet), and the character code for 2 (50) is bigger than the character code of 1 (49), so this yields false.

It comes down to a lexographical sorting (i.e. by character codes) and not a numerical one, even if the elements are numbers (because of the string coercion).

Basically comparing arrays is not recommended. It is implicitly defined as string comparison, but this can yield surprising results.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • 1
    @jAndy: It would, but then again it only works nicely for one-element arrays. `-2 - 1` would be a bit clearer... – pimvdb Nov 30 '11 at 16:15
9

There's no such thing as JavaScript array comparison in any form similar to what you describe.

What's happening in all cases is that your arrays are being converted first to strings by joining their contents together. Thus, the string "-2" is not less than the string "-1", because the character "2" comes after "1" in the character set. Similarly, "-1,1" is less than "0,0" because the "-" character comes before the digits.

You can see for yourself that in all cases your comparisons:

array1 < array2

get exactly the same results as:

("" + array1) < ("" + array2)

or:

array1.join(",") < array2.join(",")
Pointy
  • 405,095
  • 59
  • 585
  • 614
1

I couldn't find an answer about how to actually compare arrays in Javascript and get "expected" results, so here is the code

compareArrays = function(a, b) {
  var elA, elB, i, len; 
  for (i = 0, len = Math.min(a.length, b.length); i < len; i++) {               
    elA = a[i], elB = b[i];
    if (elA > elB) return 1;
    if (elA < elB) return -1;
  }
  return b.length - a.length;
};

console.log(compareArrays([-2], [-1])) # -1
console.log(compareArrays([], [])) # 0
console.log(compareArrays([null], [undefined])) # 0
console.log(compareArrays([1, 2, 3], [1, 2, 3, 4])) # 1
console.log(compareArrays([0, 2], [0, 1])) # 1
console.log(compareArrays([1], [NaN])) # 0
console.log(compareArrays([NaN], [1])) # 0
Valentin Nemcev
  • 4,940
  • 2
  • 20
  • 21