2

So I came across this weird sorting bug in JS when this sequence is sorted:

console.log([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 9].sort());

which outputs

[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 9]

so I tried a few other cases where the last 9 was 0 - 8. The sorting works as expected for both 0 and 1, but for numbers between 2 - 9, the sequence is not sorted.

[0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 5]

Behavior is same on Firefox and Chrome

I didn't know where else to go so I though I'd share here.

Test: https://jsbin.com/lixasowubi/edit?js,console

scarface382
  • 97
  • 1
  • 7
  • It's explained in [*ECMA-262*](http://ecma-international.org/ecma-262/8.0/#sec-array.prototype.sort), the relevant part is [*ยง22.1.3.25.1*](http://ecma-international.org/ecma-262/8.0/#sec-sortcompare) steps 5 and 6: *Let xString be ? ToString(x)*, i.e. by default the values are sorted as strings, regardless of their Type in the array. โ€“ RobG Jan 11 '18 at 07:20
  • https://stackoverflow.com/questions/1063007/how-to-sort-an-array-of-integers-correctly โ€“ Pushpendra Kumar Jan 11 '18 at 07:25

2 Answers2

2

By default, the sort() method sorts the values as strings in alphabetical and ascending order.

This works well for strings ("Apple" comes before "Banana"). However, if numbers are sorted as strings, "25" is bigger than "100", because "2" is bigger than "1".

https://www.w3schools.com/jsref/jsref_sort.asp

To sort as numbers please use

.sort(function(a, b) {return a - b }) // Ascending
.sort(function(a, b) {return b - a }) // Descending
Kosh
  • 16,966
  • 2
  • 19
  • 34
0

Javascript sorts alphabetically. This means that "10" is lower than "5", because "1" is lower than "5".

To sort numerical values you need to pass in numerical comparator like this:

function sorter(a, b) {
  if (a < b) return -1;  // any negative number works
  if (a > b) return 1;   // any positive number works
  return 0; // equal values MUST yield zero
}

[1,10, 5].sort(sorter);
Or you can cheat by passing simpler function:

function sorter(a, b){
  return a - b;
}

[1, 10, 5].sort(sorter);

Logic behind this shorter function is that comparator must return x>0 if a > b, x<0 if a < b and zero if a is equal to b. So in case you have

a=1 b=5 a-b will yield negative(-4) number meaning b is larger than a

a=5 b=1 a-b will yield positive number(4) meaning a is larger than b

a=3 b=3 a-b will yield 0 meaning they are equal

Abdus Sattar Bhuiyan
  • 3,016
  • 4
  • 38
  • 72