Sorting strings with JS (properly)

It seems like such a basic task – how to sort a list of strings alphabetically.

The easiest way, and what you’d probably stumble across first, is a simple sort function:

1
arr.sort();

Or using the sort() function and passing a compare function:

1
arr.sort((a, b) => a > b);

Or sorting on object property:

1
2
3
4
5
arr.sort(function(a, b){
    if(a.name < b.name) return -1;
    if(a.name > b.name) return 1;
    return 0;
})

This is the most common answer when searching Google/Stack Overflow on how to sort an array. It works for simple strings, however you can quickly run into issues when numbers get involved where 10 can appear before 2 etc. And then there are special characters and languages other than English – what determines where they appear in an alphabetical list?

It’s not easy to find this answer – is it assumed knowledge? I quickly discovered a bunch of highly complicated sorting functions that people had glued together on Stack Overflow. But I thought surely there is a simpler way for such a basic and common task.

Intl.Collator to the rescue

JavaScript has an Internationalisation API called Intl (MDN) which provides tools for sorting text (among many other things) in a specific language, and taking into account letter case, numbers and special characters.

You first need to create a Collator object using Intl.Collator:

1
let collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });

A locale can be provided as the first argument (where I have used ‘undefined’) to specify a language other than the default (see Collator in MDN)

Once we have the collator we can use its ‘compare’ function in the Array.sort:

1
2
3
4
5
6
let arr = [
  "First item",
  "The second item",
  "Item 3"
];
arr.sort(collator.compare);

Or if you need to compare a property on an object:

1
2
3
4
5
6
let arr = [
  {name: "First item" },
  {name: "The second item" },
  {name: "Item 3" }
];
arr.sort((a, b) => collator.compare(a.name, b.name));
Posted toJavascript