Fabio Costantini
Fabio Costantini

Reputation: 31

Javascript sort() isn't working for arrays of more than 10 objects in Chrome

While using sort() method in Javascript, I'm not able to correctly sort an array of more than 10 objects. This happens only in Google Chrome; with Firefox and IE it works.

I have an array of 11 objects with two properties, number and name; I'd like to order these object per number and then per name, but with Chrome it doesn't work.

This is the code of the whole page:

<!DOCTYPE html>
<HTML>
<HEAD>
    <SCRIPT>
        var availableTags = [
            {number: 0,name:"Consigli"},
            {number: 0,name:"De sanctis"},
            {number: 0,name:"Perin"},
            {number: 1,name:"Bonucci"},
            {number: 2,name:"Essien"},
            {number: 2,name:"Florenzi"},
            {number: 2,name:"Hernanes"},
            {number: 2,name:"Martinho"},
            {number: 2,name:"Montolivo"},
            {number: 2,name:"Parolo"},
            {number: 2,name:"Perez"}
        ];

        function sortPlayers(a, b) {
            var result = (parseInt(a.number) > parseInt(b.number));
            if( (!result) && (parseInt(a.number) == parseInt(b.number)) ) {
                result = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
            }
            return result;
        }

        function updateFormation() {
            availableTags.sort( sortPlayers );
            var html = "";
            for (var i = 0; i < availableTags.length; i++) {
                html += availableTags[i].number + " " + availableTags[i].name + "\n";
            }
            alert(html);
        }
    </SCRIPT>
</HEAD>
<BODY>
    <script type="text/javascript">
        updateFormation();
    </script>
</BODY>

At the following link: http://blog.rodneyrehm.de/archives/14-Sorting-Were-Doing-It-Wrong.html I read that "Chrome will sort arrays using InsertionSort if the array has 10 or less elements.": maybe this may help...

Does anybody can help me?

Upvotes: 3

Views: 2737

Answers (3)

thefourtheye
thefourtheye

Reputation: 239623

Array.prototype.sort method expects the sort helper method to return three different types of values.

1. Negative number - If the first element is smaller

2. Positive number - If the second element is smaller

3. Zero            - If both the elements are equal

So, your sortPlayers has to be tweaked a little, like this

function sortPlayers(a, b) {
    if (a.number === b.number) {
        return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
    } else {
        return a.number > b.number ? 1 : -1;
    }
}

Since a.number and b.number are actually integers, you can straight away write like this

return a.number - b.number;

Upvotes: 5

Minko Gechev
Minko Gechev

Reputation: 25682

You have mistake at this line:

var result = (parseInt(a.number) > parseInt(b.number));

it should be:

var result = (parseInt(a.number) - parseInt(b.number));

sort accepts callback, which should return negative number, positive number or zero. In your code when result is true the function sortPlayers returns true.

Since if result is 0 a.number and b.number will be equal your function could be transformed to:

 function sortPlayers(a, b) {
    var result = (parseInt(a.number) - parseInt(b.number));
    if (!result) {
      result = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
    }
    return result;
 }

Upvotes: 0

jfriend00
jfriend00

Reputation: 707876

The sort callback function needs to return negative, 0 or positive number. You are returning a boolean in some cases which can yield inconsistent results and does not match the specification. A simple subtraction of two comparison numbers yields the proper negative, 0 or positive result that the comparison function needs:

function sortPlayers(a, b) {
    var result = a.number - b.number;
    if (result !== 0) {
        return result;
    }
    return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
}

Working demo: http://jsfiddle.net/jfriend00/Q6Qa2/

In addition, there is no need to use parseInt() on things that are already numbers. And, if you did use parseInt(), you MUST pass the radix value (the second argument) or parseInt() may wrongly guess the radix value.

Upvotes: 1

Related Questions