Explain Codes LogoExplain Codes Logo

How to perform case-insensitive sorting array of string in JavaScript?

javascript
prompt-engineering
functions
callbacks
Nikita BarsukovbyNikita Barsukov·Oct 28, 2024
TLDR

Effectively sort strings in an array without being susceptible to case dependency using the built-in sort() method and a comparator that leverages toLowerCase():

const fruits = ['Banana', 'apple', 'Cherry']; // DJ's got the beats, dancers got the moves. Let's get it sorted! 😎 fruits.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); console.log(fruits); // ['apple', 'Banana', 'Cherry']

Method Breakdown

There's more than one way to skin a cat, or, in our case, sort strings. Let's dive in!

localeCompare() in sorting

localeCompare() provides an option for easy case-insensitive sorting:

const strings = ['Bænjamin', 'benjamin', 'BENJAMIN']; // Let's end the case discrimination! ✊ strings.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' })); // Prints out: ['Bænjamin', 'benjamin', 'BENJAMIN']

In the above example, { sensitivity: 'base' } directs localeCompare to ignore differences in case and accents -- which is what we want for universal case-insensitive sorting.

Efficient sorting with Intl.Collator()

If you need to optimize performance for large datasets or frequent sort operations, Intl.Collator().compare is your pal:

const collator = new Intl.Collator(undefined, { sensitivity: 'base' }); const words = ['zebra', 'Zebra', 'ZEBRA']; // 'collator.compare'? Sounds like we're hunting for replicants 🤖 words.sort(collator.compare);

Sorting Pitfalls

When sorting strings, there are few things to keep in mind.

Execution order

Ensuring .toLowerCase().localeCompare() sequence is critical for uniformity before comparison.

More than just case-insensitivity

Create a more sophisticated sorting logic including numbers and special characters when your string sorting goes beyond simple cases:

const alnums = ['alex', 'Alex', 'alex1', 'Alex2']; // 'alex' first, 'Alex' oh wait, 'alex1' first! How about 'Alex2'? It's sortedception! 🤯 alnums.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()) || a.localeCompare(b)); // Prints out: ['alex', 'Alex', 'alex1', 'Alex2']

Differences in sort method behaviour

The Array.sort() method treats each item as a Unicode point, not as a string, causing unexpected results.

Custom Sorting for Accuracy

Accuracy, as they say, takes you from good to great.

Handling corner cases

Testing your sorting method against inputs like numeric strings, accented characters and multiple languages ensures a reliable output.

Cross-browser compatibility

Cross-check the compatibility of localeCompare() across different browsers to ensure consistent results.

Looks like a sorted job!

The principle here is simple - the sorting mechanism treats uppercase and lowercase as equal, letting you focus on what really matters.`

Best Practices for Readability

Refactor your code for legibility and extendibility.

The DRY principle

Develop a reusable sortCaseInsensitive() function:

function sortCaseInsensitive(arr) { return arr.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); // The name's Bond..Sort. Case Insensitive Sort. *cue music* 🎶 }

Better refactor for toLowerCase()

Assign toLowerCase() to variables before comparison to evade duplicate calls:

const sortInsensitive = (a, b) => { const lowerA = a.toLowerCase(); const lowerB = b.toLowerCase(); return lowerA.localeCompare(lowerB); };

Standardize similar strings

Normalize the strings to improve their comparability using normalize():

const stripDiacritics = (str) => str.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); // Ascii rules, diacritics drools. (Just kidding, we love all characters equally) 💙