3

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?

3 Answers 3

5

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;
Sign up to request clarification or add additional context in comments.

2 Comments

+1 But you could use a.number - b.number instead of a.number > b.number ? 1 : -1.
I've been getting weird results with almost exact code while using > to compare a.name strings. Odd I expected string comparison to work fine without the localeCompare
1

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.

Comments

0

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

8 Comments

There's no reason to use parseInt() here. The values are already numbers. In addition, one should always pass the radix parameter when using parseInt().
First: @Fabio uses parseInt, he might need it. Second: the radix parameter is not required. By default in ES5 the default radix parameter is 10.
Does your code ALWAYS run in an ES5 browser? If so, what part of the web do you find that in? Prior to ES5, the radix does not necessarily default to 10.
Some of the users still use IE6 but we have to move forward.
Uhhh, this particular behavior includes IE7 and IE8. Why is it so hard to be safe and include an extra argument? Geez.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.