9

This seems like a simple sort, yet JavaScript is giving an incorrect result.

Am I doing something wrong or is this a language quirk?

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

[ 1, 10, 5 ]

Community
  • 1
  • 1
kabir
  • 747
  • 2
  • 6
  • 6
  • 5
    Seems perfectly well ordered for a *lexical order*. – deceze Jan 09 '14 at 12:12
  • 4
    I hate to quote Atwood, but...[the first rule of programming](http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html) is relevant here. – T.J. Crowder Jan 09 '14 at 12:18

6 Answers6

30

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
lukas.pukenis
  • 13,057
  • 12
  • 47
  • 81
  • 1
    This is WAY too much code! – Kelly J Andrews Jan 09 '14 at 12:17
  • @KellyJAndrews where ? Second approach is widely used. Of course you can inline it directly and minify if you prefer size > readability – lukas.pukenis Jan 09 '14 at 12:19
  • I did my example in one line, The smallest you are using is 3. – Kelly J Andrews Jan 09 '14 at 12:21
  • 4
    @KellyJAndrews talking about reusability if you use yoursort 5 times, my code will beat yours by readability, reusability, DRY approach and if you're not happy with my approach, simply delete two newlines – lukas.pukenis Jan 09 '14 at 12:23
  • @KellyJAndrews - Your one line is identical to the second example in this answer. Do you think 1 line is better than 3 because you didn't include any spaces? – Adam Jenkins Jan 09 '14 at 12:26
  • Just seems like overkill to me to perform such a small task. If all you were doing was `a-b`, perfect, but if you want `b-a`, now do you need another function, or do you pass variable? I don't think it saves you anything here. It "looks" better at first, but it's such a small thing to do. I'm all for a DRY approach as well, I'm just also an advocate for not doing something just to do it, and that's what a separate function here feels like. Sorry to state my opinion - I'll be sure to keep it to myself next time. – Kelly J Andrews Jan 09 '14 at 12:30
  • I agree it may be an overkill for such a simple task but I view this problem as a reusable one. I of course will sort numbers in my application more than once so seems logical to extract it into a function. Now as I have a function, why not make it as beautiful as I can? :) – lukas.pukenis Jan 09 '14 at 12:34
  • 1
    This code can be shortened using an [Arrow Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). `numberArray.sort((a, b) => (a - b));` **Note: check if your JS engine supports Arrow Functions.** – Константин Ван Dec 28 '15 at 09:49
  • I don't think it's "cheating" to subtract the two values, that's exactly how to compare two numeric values. The -1, +1, or 0 is the 'cheating' where you're returning a fictitious value with a 'good enough' estimate of the difference between the two values. (Additionally, under the covers `if (a < b) return -1` is going to do something like say *"subtract the values, and if the difference is negative, then evaluate to true, and if the result is true, then return negative 1"* when you could just say "return the difference, the end"). – Dave Cousineau Nov 24 '17 at 23:49
  • Subtracting two values and checking flag state is how comparing is done at assembly level at least on x86 – lukas.pukenis Nov 26 '17 at 13:17
  • this was perfect for what i was trying to do. – PH83 Oct 29 '18 at 14:11
6

You have to pass a function to the sort method.

var points = [5, 10, 1];
points.sort(function(a,b){return a-b});

Here is a working fiddle.

Kelly J Andrews
  • 5,083
  • 1
  • 19
  • 32
0

Default sort order is alphabetic and ascending. If you want to sort the number you could do something like this:

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

var numArray = [140000, 104, 99];
numArray.sort(sortNumber);
Jacob
  • 3,580
  • 22
  • 82
  • 146
0
function sortit(a, b){ return (a-b); }
[1, 5, 10].sort(sortit);
NewInTheBusiness
  • 1,465
  • 1
  • 9
  • 14
0

You may try:

[5, 10, 1].sort(function(a, b){ return a - b })   # print [1, 5, 10]
Dhanu Gurung
  • 8,480
  • 10
  • 47
  • 60
0

you can try

[5, 10, 1].sort(function(a,b){return a-b})
Sirko
  • 72,589
  • 19
  • 149
  • 183
rajesh kakawat
  • 10,826
  • 1
  • 21
  • 40