Dictionary sorting in JavaScript
5 minute read
By default, the JavaScript Array.sort() function sorts arrays according to character placement within a character set. For most web content, this is UTF-8.
However, this may not always be an ideal result.
Here, we show how to define a custom sort order in JavaScript.
Process array
To illustrate, consider the following book titles, organized roughly by the year they were first published.
A Study in Scarlet
The Sign of Four
The Adventures of Sherlock Holmes
The Memoirs of Sherlock Holmes
The Hound of the Baskervilles
The Return of Sherlock Holmes
His Last Bow
The Valley of Fear
The Case-Book of Sherlock Holmes
To print an array containing these titles to a web page, you might use something like this:
var iTotal = astrTitles.length;
if ( iTotal > 0 ) {
for ( var iTitles = 0; iTitles < iTotal; iTitles++ ) {
var str = astrTitles[ iTitles ];
writeTitle( str );
}
}
Here, the writeTitle() function represents the code needed to display the title on the target device.
function writeTitle( strTitle ) {
var obj = document.getElementById( "pOutput" );
obj.textContent += strTitle + "\n";
}
Example 1: A JavaScript function to write string values to a webpage. (Try it out)
Sort an array
When asked to sort the array alphabetically, you might call the Array.sort() function:
var iTotal = astrTitles.length;
if ( iTotal > 0 ) {
astrTitles.sort();
for ( var iTitles = 0, iTitles++, iTitles < iTotal ) {
writeTitle( astrTitles[ iTitles ] );
}
}
Example 2: JavaScript code to sort an array before process it. (Try it out)
When run, this leads to the following:
A Study in Scarlet
His Last Bow
The Adventures of Sherlock Holmes
The Case-Book of Sherlock Holmes
The Hound of the Baskervilles
The Memoirs of Sherlock Holmes
The Return of Sherlock Holmes
The Sign of Four
The Valley of Fear
From a technical view, these might be the results you expect; however, your users might have different ideas.
Move leading articles
As an alternative, consider:
Adventures of Sherlock Holmes, The
Case-Book of Sherlock Holmes, The
His Last Bow
Hound of the Baskervilles, The
Memoirs of Sherlock Holmes, The
Return of Sherlock Holmes, The
Sign of Four, The
Study in Scarlet, A
Valley of Fear, The
Here, leading articles (a, an, and the) are moved to the end of the title. To some, these results are clearer and more logical.
This strategy is common to business filing systems and known by different names, including dictionary sorting and alphabetic collation.
For a detailed look, see Section 4.6 (PDF) of “Guidelines for Alphabetical Arrangement of Letters and Sorting of Numerals and Other Symbols”, by Hans H. Wellisch, 1999 National Information Standards Organization (NISO) Technical Report TR02-1999.
To create a custom function that does this in JavaScript, you might use something along these lines:
function moveLeadingArticle( sInput ) {
var sResult = sInput.toLocaleLowerCase();
var aArticles = [ 'a', 'an', 'the' ];
var aWords = sResult.split(/\s/);
if ( aArticles.indexOf( aWords[0] ) > -1 ) {
sResult = aWords.slice( 1 ).join( ' ' );
sResult += ', ' + aWords[0];
}
return sResult;
}
Example 3: A custom function to move leading titles to the end of an input string. (Try it out)
Here, the input parameter value is:
- Converted to lowercase.
- Split into individual words.
- The first word is compared to a list of known articles (a, an , the).
- When a title starts with an article, the article is moved to the end of the title.
Here are a couple of examples:
-
moveLeadingArticle( "His Last Bow" )
returnshis last bow
-
moveLeadingArticle( "The Sign of Four" )
returnssign of four, the
Custom sort order
You can create a custom sort order by passing an anonymous function to the Array.sort() function.
var iTotal = astrTitles.length;
if ( iTotal > 0 ) {
if ( aResultsArray.length > 1 ) {
aResultsArray.sort( function( a, b ) {
var SortTermA = moveLeadingArticle( a );
var SortTermB = moveLeadingArticle( b );
return SortTermA.localeCompare( SortTermB );
} );
}
Example 4: Performing a custom sort using an anonymous function. (Try it out)
Here, the anonymous function calls the custom function when comparing string values. When run, these titles are sorted in dictionary order (shown earlier).
Example #3 shows this in action.
International concerns
This example essentially demonstrates how to perform a custom sort using JavaScript.
Unfortunately, the actual algorithm relies on a specific behavior used to sort titles written in English using Latin characters. It might be useful for book lists, music collections, or even video games involving extensive player inventory systems.
Beyond these cases, the example might have limited value. It doesn’t account for alternate alphabets, collation patterns, or even languages that do not support articles.
From an Internationalization (I18N) perspective, this technique implements an edge-case scenario used for a single language. (I18N is the art of writing apps to support users and their native assumptions.)
If you’re designing a (potentially) global solution, it may be wise to take a few moments to consider:
- Dictionary sorting has not been codified as a standards-based collation technique. As a result, it’s not supported by commonly-used libraries.
- Exceptions require custom code, which complicates maintenance and potentially hinders performance.
- There may be insufficient resources to support edge cases at a global scale.
- American sorting conventions may not scale effectively to other English speakers.
The Intl.collator() object is typically suggested as a good resource for international concerns. (Unfortunately, few options seem to support this specific scenario for English.)
As with many such discussions, you’ll have to balance customer satisfaction against practical development resources.
To learn more about I18N, see:
- Handling character encodings in HTML and CSS (W3C)
- International Components for Unicode (ICU)
- The Unicode Common Local Data Repository (CLDR)
Vital statistics
- Updated: 8 May 2024 - Rewritten to align to current style guidelines, support the site revamp, and discuss the I18N perspective.
- First post: 26 January 2017