Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 813
Fresh Friend Avatar asked Jan 03 '18 17:01

Fresh Friend


2 Answers

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;
}
like image 87
Marcus Parsons Avatar answered Sep 30 '22 20:09

Marcus Parsons


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.

like image 24
ryanyuyu Avatar answered Sep 30 '22 22:09

ryanyuyu