JavaScript

The Only JavaScript Sorting Guide You'll Ever Need

Today, we are going to learn about sorting in JavaScript. Starting with the history and algorithm used for .sort(). Then learning how to sort primitives and objects. Let's jump in!

Written by Gregory Gaines
4 min read
0 views
Pile of legos
Photo by Xavi Cabrera on Unsplash

Table of Contents

Hello Reader 👋🏽

I was tired of searching on Google when I was unsure of how to sort whatever data I'm using in JavaScript, so I decided to write it all in one place.

Today, we are going to learn about sorting in JavaScript. Starting with the history and algorithm used for .sort(). Then learning how to sort primitives and objects. Let's jump in!

JavaScript's sort() function 📏

The .sort() function sorts an array in-place (meaning no copy is made) and returns the sorted array. We can't modify the algorithm used by .sort(), but we can modify how it compares array elements by passing a compare function.

JS
1// Native, without a compare function 2sort() 3 4// With an arrow pointing compare function 5sort((a, b) => { 6 ... 7}) 8 9// Passing a compare function 10sort(compareFn)

Implementation History

In Chrome, back in the ye-old days, the sorting algorithm wasn't as good as today. One of its previous implementations included insertion sort O(n2) 🤢.

Today we are in a better state with a modification of Merge Sort named Tim Sort O(n log n) 😊. Initially created by Time Peters as an adaptive stable Merge Sort variant.

A stable sorting algorithm means if two values of the same value sit next to each other, they maintain the same order after sorting. You'd be surprised how many algorithms depend on this.

Sorting Primitives

Let's go over how to sort primitives with .sort().

Sorting an Array of Strings

The sort() function works how you'd expect for strings.

JS
1const names = ["Darui", "Bee", "Naruto", "Ada", "Sasuke", "Baki", "A"]; 2 3console.log(names.sort());
JS
1// Output: ["A", "Ada", "Baki", "Bee", "Darui", "Naruto", "Sasuke"]

JavaScript by default sorts in Lexicographical order. Lexicographical order means sorted alphabetically sort of like a dictionary. If two strings are equal, then the shortest one is put first.

JS
1// Lexicographical order 2const str = ["aab", "ba", "aac", "bab", "aaa", "Aab", "aaaa"]; 3 4// Results 5"Aab" // Uppercase letters take precedence 6"aa|a" 7"aa|aa" // Is equal to "aaa" but is longer 8"aa|b" // The 3rd char 'b' comes the third char 'a' in the strings above. 9"aa|c" // The last char 'c' comes after 'b' 10"ba" // The first char 'b' comes after 'a' in the above strings 11"bab"

Sorting an Array of Numbers 🧮

Using .sort() on numbers is a bit tricky. It DOES NOT work natively.

JS
1const scores = [9, 80, 19, 4, 20, 53]; 2 3// Wrong ❌ 4console.log(scores.sort());
JS
1// Wrong order 👎🏽 2// Output: [19, 20, 4, 53, 80, 9]

By default, JavaScript sorts in Lexicographical order. Great for strings but terrible for numbers. We have to pass a compare function.

Who gets sorted first?

Compare Function

Compare function interpretation

The compare function returns an integer which .sort() uses to determine the order when comparing elements.

JS
1function compareNumbers(a, b) { 2 if (a < b) { 3 return -1; // sort a before b 4 } else if (a > b) { 5 return 1; // sort a after b 6 } 7 8 return 0; // keep a and b in the same order 9}

When two elements are passed to the compare function, if it returns less than 0, a is put first. If the result is greater than 0, b is put first. If the result is equal to 0, keep a and b in the same order. Ex. a(3) - b(2) is 1 which puts b(2) in front of a(3).

To properly sort numbers, we introduce a compare function to sort numbers in ascending order.

JS
1let scores = [9, 80, 19, 4, 20, 53]; 2 3// Sort in ascending order ✅ 4scores.sort((a, b) => { 5 return a - b; 6}); 7 8console.log(scores);
JS
1// Output: [4, 9, 19, 20, 53, 80]

Descending Order

Descending order is an easy 1 line change. Instead of using a - b, use b - a to reverse the order. Take our a(3) - b(2) example from earlier. If we change it to b(2) - a(3), we get -1. This instead puts a(3) in front of b(2).

JS
1let scores = [9, 80, 19, 4, 20, 53]; 2 3// Sort in descending order 4scores.sort((a, b) => { 5 return b - a; 6}); 7 8console.log(scores);
JS
1// Output: [80, 53, 20, 19, 9, 4]

Sorting an Array of Objects 🏎️

In JavaScript, an object is a variable with a collection of properties in key:value pairs.

JS
1// Array of objects with two properties, 'name' and 'titansDefeated'. 2const characters = [{ 3 name: 'eren', 4 titansDefeated: 1 5 }, 6 { 7 name: 'mikasa', 8 titansDefeated: 20 9 }, 10 { 11 name: 'levi', 12 titansDefeated: 90 13 }, 14 { 15 name: 'armin', 16 titansDefeated: 10 17 }, 18];

Since objects have multiple properties, we pass a compare function to sort by the property we want.

Sorting by the amount of titansDefeated in ascending order.

JS
1const characters = [{ 2 name: 'eren', 3 titansDefeated: 1 4 }, 5 { 6 name: 'mikasa', 7 titansDefeated: 20 8 }, 9 { 10 name: 'levi', 11 titansDefeated: 90 12 }, 13 { 14 name: 'armin', 15 titansDefeated: 10 16 }, 17]; 18 19characters.sort((a, b) => { 20 return a.titansDefeated - b.titansDefeated; 21}); 22 23console.log(characters);
JS
1// Output: [{ 2// name: "eren", 3// titansDefeated: 1 4// }, { 5// name: "armin", 6// titansDefeated: 10 7// }, { 8// name: "mikasa", 9// titansDefeated: 20 10// }, { 11// name: "levi", 12// titansDefeated: 90 13// }]

Sorting by the amount of titansDefeated in descending order.

JS
1const characters = [{ 2 name: 'eren', 3 titansDefeated: 1 4 }, 5 { 6 name: 'mikasa', 7 titansDefeated: 20 8 }, 9 { 10 name: 'levi', 11 titansDefeated: 90 12 }, 13 { 14 name: 'armin', 15 titansDefeated: 10 16 }, 17]; 18 19characters.sort((a, b) => { 20 return b.titansDefeated - a.titansDefeated; 21}); 22 23console.log(characters);
JS
1// Output: [{ 2// name: "levi", 3// titansDefeated: 90 4// }, { 5// name: "mikasa", 6// titansDefeated: 20 7// }, { 8// name: "armin", 9// titansDefeated: 10 10// }, { 11// name: "eren", 12// titansDefeated: 1 13// }]

Sorting by names in lexicographical order.

JS
1const characters = [{ 2 name: 'eren', 3 titansDefeated: 1 4 }, 5 { 6 name: 'mikasa', 7 titansDefeated: 20 8 }, 9 { 10 name: 'levi', 11 titansDefeated: 90 12 }, 13 { 14 name: 'armin', 15 titansDefeated: 10 16 }, 17]; 18 19// Sort names in case-insensitive 20// lexicographical order 21characters.sort((a, b) => { 22 // Convert to uppercase so we don't have 23 // to worry about case differences. 24 const nameA = a.name.toUpperCase(); 25 const nameB = b.name.toUpperCase(); 26 27 if (nameA < nameB) { 28 return -1; 29 } 30 if (nameA > nameB) { 31 return 1; 32 } 33 34 // names must be equal 35 return 0; 36}); 37 38console.log(characters);
JS
1// Output:[{ 2// name: "armin", 3// titansDefeated: 10 4// }, { 5// name: "eren", 6// titansDefeated: 1 7// }, { 8// name: "levi", 9// titansDefeated: 90 10// }, { 11// name: "mikasa", 12// titansDefeated: 20 13// }]
Levi said "sort faster"

Final Thoughts 💭

Here's everything you need for sorting in JavaScript all in one place. In Chrome, .sort() is implemented using the Tim Sort algorithm. By default .sort() sorts in lexicographical order, great for strings but not so much for anything else. We pass a compare function for numbers and objects to define the sorting order.

I'm Gregory Gaines, a goofy software engineer @Google who's trying to write good articles. If you want more content, follow me on Twitter at @GregoryAGaines.

Now go create something great! If you have any questions, hit me up on Twitter (@GregoryAGaines); we can talk about it.

Thanks for reading!

About the author.

I'm Gregory Gaines, a software engineer that loves blogging, studying computer science, and reverse engineering.

I'm currently employed at Google; all opinions are my own.

Ko-fi donationsBuy Me a CoffeeBecome a Patron
Gregory Gaines

You may also like.

Comments.

Get updates straight to your mailbox!

Get the latest blog updates about programming and the industry ins and outs for free!

You have my spam free, guarantee. 🥳

Subscribe