24

I have tried this code

function sort() {
    var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9];
    alert(ary.sort(function(a, b) {return a < b;}));
}
sort();

but the result is

[1, 2, 2, 1.1, 0.9, 1.2, 1.5, 1, 1.3, 0.4, 0.4, 0.4, 0.2, 0.2]

It works if length of array is short. But it doesn't work for long array. Thanks.

7
  • 1
    you can shorten that to return ary.sort((a,b) => a < b); Commented Jan 3, 2018 at 17:12
  • Sorry, just mistake. please try edited one. Commented Jan 3, 2018 at 17:14
  • 4
    Try function(a, b) {return a - b;} Commented Jan 3, 2018 at 17:14
  • 4
    @SterlingArcher Array.prototype.sort() expects an integer return, not boolean ;) Commented Jan 3, 2018 at 17:16
  • 1
    @Archer good call, I was more focused on the syntax than the sort issue lol Commented Jan 3, 2018 at 17:17

4 Answers 4

43

Edited with additional info:

My apologies, but the shortest answer for this question is just:

function sort() {
    var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9];
    // use custom compare function that sorts numbers ascending
    alert(ary.sort(function(a, b) {
        return a - b;
    }));
}

sort();

Note that if a compare function is not supplied to the sort method, elements are sorted by converting them to strings and comparing strings in Unicode code point order. So [1, 2, 10].sort() produces [1, 10, 2] because "10", as a string, comes before "2". The code above will return the array sorted from smallest to largest correctly.

You can sort largest to smallest (descending order) by reversing a and b within the return statement:

function (a, b) {
    return b - a;
}
Sign up to request clarification or add additional context in comments.

5 Comments

This is wrong. Arrays would be sorated as strings by default.
A quick counterexample: [9, 99, 901].sort() returns [9, 901, 99], which is clearly not in numerical order.
sorry, it is Still wrong about default behavior.
Please let me know where I am wrong. But quoting directly from the MDN article for the sort method: "If compareFunction is not supplied, elements are sorted by converting them to strings and comparing strings in Unicode code point order."
ary.sort((a, b) => b - a)
31

You sorting is failing because your comparison function does not meet the specifications for Array.sort:

  • If compareFunction(a, b) is less than 0, sort a to an index lower than b, i.e. a comes first.
  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
  • If compareFunction(a, b) is greater than 0, sort b to an index lower than a, i.e. b comes first.
  • compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.

Your comparison function returns a boolean, which is effectively only returning the values 0 and 1. You should fix your comparison function according to the spec like in David's answer. Here's a simple comparison function1:

var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9];
console.log(ary.sort(compareDecimals));

function compareDecimals(a, b) {
    if (a === b) 
         return 0;

    return a < b ? -1 : 1;
}

The other answers (of using function { return a - b; } take advantage of mathematical coincidence. Namely that equal values have a difference of 0. This works for "normal" values, but it's prone to errors when your data contains values like Inifinity or Number.MIN_SAFE_INTEGER.


1. As noted in the comments, this function does not address all of the crazy javascript number behavior, for example that NaN === NaN evaluates to false. Likewise for dealing with mixed-type arrays. Engineer your comparison function as needed depending on the nature of your data.

6 Comments

The first example can also fail, for NaN, which is a number. Just saying.
@SalmanA thanks. I've noted this in a footnote since it's not really the focus of the core issue, which is about how array.sort actually works.
@ryanyuyu, thank you for bringing this up. Infinity and Number.MIN_SAFE_INTEGER do work with the default sorting method. Infinity is represented in memory as a value along with Number.MIN_SAFE_VALUE so if you add those into the array (using the default behavior), they will sort accordingly.
Let me also say that NaN works with the default function of sort (always at the end of the array), however in this comparison function, NaN will cause the sorting to go awry. The output from this: var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9, Infinity, Number.MIN_SAFE_INTEGER, NaN]; console.log(ary.sort(compareDecimals)); function compareDecimals(a, b) { if (a === b) return 0; return a < b ? -1 : 1; } is: [1.1, NaN, -9007199254740991, 0.2, 0.2, 0.4, 0.4, 0.4, 0.9, 1, 1, 1.2, 1.3, 1.5, 2, 2, Infinity]
Also, consider the fact that JS math is not precise. See stackoverflow.com/questions/5153061/…
|
4

Your code has a typo in alert.

Anyway the correct implementation is -

function sort() {
        var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9];
        return ary.sort(function(a, b) {return a - b;});
}
    
alert(sort());

outputs - [0.2, 0.2, 0.4, 0.4, 0.4, 0.9, 1, 1, 1.1, 1.2, 1.3, 1.5, 2, 2]

(use b - a to change the sort order).

Comments

3

Try:

var ary = [2, 1, 0.4, 2, 0.4, 0.2, 1.5, 1, 1.1, 1.3, 1.2, 0.2, 0.4, 0.9];

function compare(a, b) {
    if (a < b) {
        return -1;
    } else if (a > b) {
        return 1;
    } else {
        return 0;
    }
}


ary = ary.sort(compare);
alert(ary);

6 Comments

Why not simplify this to just function compare(a, b) { return a - b }?
ah yes, that makes sense :P
It's not the same, because JS floating point math is not precise, so a - b may not end up equaling 0.
@Matthias: They are not exact, but if a === b then a - b === 0.
@cpcallen ah you're right! Also MDN states that the return value can be any negative/positive number, so a - b is perfectly fine!
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.