Explain Codes LogoExplain Codes Logo

Natural sort of alphanumerical strings in JavaScript

javascript
performance
regular-expressions
sorting-algorithms
Alex KataevbyAlex Kataev·Nov 16, 2024
TLDR

To immediately sort alphanumeric strings naturally, use the localeCompare function with the { numeric: true } option:

const numsAndStringsSort = (a, b) => a.localeCompare(b, undefined, { numeric: true }); // Usage: const items = ['item1', 'item12', 'item2']; console.log(items.sort(numsAndStringsSort)); // ['item1', 'item2', 'item12']

This single line of code provides an intuitive and human-friendly sorting of your data.

Boost performance using Intl.Collator

For operations on larger datasets where performance comes into play, employ the Intl.Collator object to achieve a faster sort:

const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); const collatorSort = (a, b) => collator.compare(a, b); // Usage on large array: const largeItems = [/* LARGE ARRAY */]; console.log(largeItems.sort(collatorSort)); // Sorting: Engage ludicrous speed!

This approach benefits larger arrays, saving those precious milliseconds, and thus enhancing the overall application performance.

Precision sorting with regular expressions

Supplement your sorting algorithm with regular expressions (regex) when your strings call for an additional level of precision:

const precisionSort = (a, b) => a.replace(/^(\d+)/, '000$1').slice(-4) .localeCompare(b.replace(/^(\d+)/, '000$1').slice(-4), undefined, {numeric: true}); // Usage: const mixedItems = ['2files', '10files', '1file']; console.log(mixedItems.sort(precisionSort)); // Output: ["10-4 good buddy"]

Case-insensitivity sorting

When dealing with data where case sensitivity doesn't matter, you can ensure a proper sort irrespective of the strings' case using sensitivity: 'base':

const caseInsensitiveSort = (a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }); // Usage: const mixedCaseItems = ['Item1', 'item2', 'item10', 'Item12']; console.log(mixedCaseItems.sort(caseInsensitiveSort)); // I'm in-cased to sort!

Employing libraries for feature-rich sorting

For complex sorting requirements, libraries like natural-orderby can be a game-changer:

import { orderBy } from 'natural-orderby'; const items = ['1item', '10item', '2item']; console.log(orderBy(items, [(value) => value ])); // Resorting to use a library

In the real world where time matters, employing the right library can be both a timesaver and a lifesaver.

Ensuring browser compatibility

LocaleCompare and Intl.Collator are supported by modern browsers like Chrome, Firefox, IE11. However, it's always good practice to test your implementation across the environments you target:

// Validate sort results in the desired environment console.log(['item1', 'item12', 'item2'].sort(numsAndStringsSort)); // [[ me, checking you...]]

Beware, sorting very large arrays may impact performance. In such cases, optimize your approach or use a library designed for speed.

Consistent results through input validation

Input validation can almost seem like magic in preventing unexpected results:

const isValidItem = item => typeof item === 'string' && item.trim() !== ''; const validatedItems = items.filter(isValidItem); console.log(validatedItems.sort(numsAndStringsSort)); // "Expecto Patronum" - Harry Potter

By validation, we ensure the inputs are real strings and their sort behaviour remains consistent.