'Array sort is not working correctly in JavaScript [duplicate]

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.



Solution 1:[1]

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.

Solution 2:[2]

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);

Solution 3:[3]

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).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 David Anthony Acosta
Solution 3 planet_hunter