A series of spheres, nested inside each other

Elements often need to be sorted: think of an array of game scores that need to be arranged from high to low to determine player rank. Unfortunately, the standard JavaScript sort() method has some surprising limitations: it works well with common English words, but breaks down when faced with numbers, accented characters, or words in uppercase.

Sorting Alphabetically

At first blush, sorting an array alphabetically should be straightforward. In the console:

var fruit = ["butternut squash", "apricot", "cantaloupe"];
fruit.sort();

> "apricot", "butternut squash", "cantaloupe"]

However, sort() faces a problem as soon as one of the elements is capitalized:

var fruit = ["butternut squash", "apricot", "Cantalope"];
fruit.sort();

> "Cantaloupe", "apricot", "butternut squash"]

This is due to the fact that, by default, sort compares Unicode code points for characters. Unicode is the way all modern computers think of characters as organized into a structured table in which each character has a unique entry code. For example, the character a has an entry of U+0061, while the code for C is U+0043 which comes before a in the Unicode table.

To sort an array that could contain mixed-case first letters, you either need to convert all the elements temporarily to lowercase, or sort() them using localeCompare and some arguments. It’s usually best to create this as a function for reusability:

function alphaSort(arr) {
    arr.sort(function (a, b) {
        return a.localeCompare(b, 'en', {'sensitivity': 'base'});
    });
}

var fruit = ["butternut squash", "apricot", "Cantaloupe"];
alphaSort(fruit)

> ["apricot", "butternut squash", "Cantaloupe"]

If you want a reverse alphabetical sort, exchange the positions of a and b in the function:

function alphaSort(arr) {
    arr.sort(function (a, b) {
        return b.localeCompare(a, 'en', {'sensitivity': 'base'});
    });
}

This also takes into account accented characters.

Numerical Sort

This doesn’t address the scenario given at the start of this article: sorting a series of high scores. With some arrays of numbers, sort works just fine, but with others it has an unpredictable response:

var highScores = [11, 57, 10, 16, 32, 100];
highScores.sort();

> [10, 100, 11, 16, 32, 57]

This response is due to the fact that sort() is doing a lexicographical comparison: it is converting the numbers into strings, and comparing the Unicode code points for the characters. Achieving a true numerical sort involves adding a compare function. This one is small enough that you may want to add it directly to sort itself:

highScores.sort( function(a,b) { return a - b; } ); 
> [10, 11, 16, 32, 57, 100]

Sorting JSON

If we have a JSON array of high scores:

var scores = [
  {
    "name": "Daniel",
    "score": 21768
  },
  {
    "name": "Michael",
    "score": 33579
  },
  {
    "name": "Alison",
    "score": 38395
  }
];

In JavaScript 2015, you can use:

scores.sort((a, b) => b.score - a.score));

For browsers without support (and sorting from lowest to highest, just to show the variation):

scores.sort(function(a, b) { return a.score - b.score })

Conclusion

Sorting in JavaScript is perhaps a little less straightforward than one might hope, but it’s my hope that these recipes will make the job a little easier.

Finding unique elements in arrays is a related and useful, but one that I’ll address in a separate article.

Photograph by Philippe Put used under a Creative Commons Attribute 2.0 Generic license

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.