---
title: "Sorting Data in JavaScript"
url: "/articles/sorting-data-javascript"
type: article
date: 2024-02-14
updated: 2024-02-14
---

# Sorting Data in JavaScript

#  Sorting Data in JavaScript 

 JavaScript provides default sorting methods for arrays, but they can sort data in unintuitive ways that are hard to predict. We cover why that happens and how to create your own sorting methods.

 By

 [  Andy Blum   ](/about/andy-blum) 

 February 14, 2024

  

Our brains are great at identifying patterns and outliers, but this becomes harder when data isnâ&#128;&#153;t in some logical order. Luckily, as developers, we can use tools to sort data into any order we desire.

## The basics of array.sort()

In Javascript, every single array has a `sort()` method. This takes all the items in the array and rearranges them into the default order. Consider the code below:

```javascript
    const fruits = ['strawberry', 'banana', 'tomato', 'apple'];
    
    fruits.sort();
    // ['apple', 'banana', 'strawberry', 'tomato']
```

The sort method rearranged the items in the array into alphabetical order - how handy! Similarly, [as of 2023,](https://caniuse.com/?search=toSorted) we can use the newer `<span>toSorted()</span>` method to create a *new* array to avoid mutating the original data. This method, however, still uses an algorithmic method of comparing data. How does it work?

### First, all array items are cast to strings

Take a moment to look at the code below and see if you can guess how the data will be sorted:

```javascript
const numbers = [25, 4, 8, 2, 18]

numbers.sort();
```

Did you guess `<span>[2, 4, 8, 18, 25]</span>`? While any human would look at those numbers and sort them that way, the sort method is casting them all to strings and sorting them the way weâ&#128;&#153;d sort words alphabetically. The actual result will be `<span>[18, 2, 25, 4, 8]</span>`.

### **Second, items are sorted by their placement on the Unicode table**

Each character has [a given encoding](https://en.wikipedia.org/wiki/List_of_Unicode_characters#Latin_script). This is what allows browsers and word processors to change the fonts of any piece of text. The visual representation of the letters humans can read has been separated from the encoding of the characters that computers can store. This encoding is numeric, and our data is sorted by that number.

This unintuitive sorting method can result in some *highly peculiar* sorting if you arenâ&#128;&#153;t looking out for it. Consider the following example:

```javascript
const data = [
  'web',
  'development',
  'is',
  'fun',
  'in',
  2023,
  '@',
  'Lullabot',
  '!',
  {firstName: 'Andy', lastName: 'Blum'}
];

data.sort();
// ['!', 2023, '@', 'Lullabot', {...}, 'development', 'fun', 'in', 'is', 'web']
```

This data doesnâ&#128;&#153;t appear sorted at all, but if you consult the Unicode table, we find this is the correct order. Numbers are always before letters, capitalized letters are always before lowercase letters, and punctuation is scattered across the table. Objects will be sorted between upper and lowercase letters because objects cast to strings are `<span>"[object Object]"</span>`.

Since the default sort order can change our dataâ&#128;&#153;s type and is tied to character encoding, we will almost always want to define a custom sorting method.

## **Sorting with a custom algorithm**

The `<span>Array.prototype.sort()</span>` and `<span>Array.prototype.toSorted()</span>` methods accept a function as their sole parameter. That [comparator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description) will be given two items from the array and is expected to return an integer. If we wanted to mimic the default functionality, our code might look like this:

```javascript
function comparator(a, b) {
  if (a.toString() < b.toString()) { return -1; }
  if (a.toString() > b.toString()) { return 1; }

  return 0;
}

data.sort(comparator);
```

Given two items from our dataset (`<span>a</span>` and `<span>b</span>` above), our comparison function will:

- return a negative number to place `<span>a</span>` before `<span>b</span>`
- return a positive number to place `<span>a</span>` after `<span>b</span>`
- return zero to leave them in the current order

A comparator for integers could look like this:

```javascript
function comparator(a, b) {
  return a - b
}
```

There are a couple of silent pitfalls to watch out for as you write a custom comparator function. First, returning a value *other than a number* or not returning a value *at all* does not trigger an error. Instead, these items are treated as being effectively identical. The function then compares the rest of the array and can leave your array only partially sorted.

Secondly, [NaN values can act counterintuitively](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN#description). While returning `<span>NaN</span>` from your comparator is effectively the same as returning 0, comparing things to `<span>NaN</span>` *always returns false,* so be careful if you start casting strings to numbers.

## **Sorting across multiple dimensions**

Once you understand how sorting works in a single dimension, you may want to sort lists in several dimensions.

For example, imagine we collect a set of users from an API. These users are sorted by their ID number by default, but weâ&#128;&#153;d like to sort them alphabetically and grouped by timezone. Sorting across multiple dimensions is as simple as sorting the array multiple times along each dimension, from the least inclusive groups to the most inclusive groups. While this may appear counterintuitive at first, weâ&#128;&#153;re asking the computer to sort items into one order and then break that order in a very specific way.

In our example, we ask the computer to sort all our users alphabetically and then sort the alphabetized list by timezone. Since the algorithm will leave items in the current order when their sorting values match, our alphabetized names will remain alphabetized within their timezone group.

Copy the code below into your devtools console to see this in action.

```javascript

(async () => {
  console.clear();
  // Gets dummy data from a github gist.
  const gist = 'https://api.github.com/gists/3c9f4df572c295252bc604d85b13a66c';
  const data = await fetch(gist).then(r => r.json());
  const users = JSON.parse(data.files['users.json'].content);
  
  // Sorts users by timezone.
  const timezoneSorter = (a, b) => {
    if (a.timezone < b.timezone) { return -1 }
    if (a.timezone > b.timezone) { return 1 }
    return 0;
  }

  // Sorts users alphabetically by last name.
  const nameSorter = (a, b) => {
    const aName = `${a.last_name} ${a.first_name}`;
    const bName = `${b.last_name} ${b.first_name}`;
    if (aName < bName) { return -1 }
    if (aName > bName) { return 1 }
    return 0;
  }

  // Sort users from most granular sort to least.
  const sorted = users.toSorted(nameSorter).toSorted(timezoneSorter);

  // Log out unsorted users to console.
  console.groupCollapsed('Unsorted Users');
  console.table(users);
  console.groupEnd();

  // Log out sorted users to console.
  console.groupCollapsed('Sorted Users');
  console.table(sorted);
  console.groupEnd();
})();
```

## **Sorting in multiple languages**

So far, when weâ&#128;&#153;ve sorted strings, weâ&#128;&#153;ve continued to rely on the Unicode placement of characters. While this works fine in a single case in English, it *does not* work reliably when we start working in other languages or mixed cases. To reliably sort text in locale-specific alphabetical order, we need to reach for the [Intl.Collator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator) class.

```javascript

// ['A', 'B', 'C', ... 'X', 'Y', 'Z']
const english = [...Array(26).keys()].map(x => (x + 10).toString(36).toUpperCase());

const germanSpecials = ['Ã&#132;', 'Ã&#150;', 'Ã&#156;', 'áº&#158;'];

// Mix the two together randomly.
const mixed = [...english, ...germanSpecials].toSorted(()=>(Math.random() - 0.5));

mixed.toSorted();
/* [ ... 'X', 'Y', 'Z', 'Ã&#132;', 'Ã&#150;', 'Ã&#156;', 'áº&#158;'] */

const german = new Intl.Collator('de')
mixed.toSorted(german.compare);
/* ['A', 'Ã&#132;', 'B', ... 'O', 'Ã&#150;', 'P', ... 'S', 'áº&#158;', 'T', 'U', 'Ã&#156;', ...] */
```

## **Conclusion**

Sorting data is a common need in web development. While JavaScript provides some default tools, they have some pitfalls and can sort things in unintuitive ways that are hard to predict. Thankfully, itâ&#128;&#153;s straightforward to write custom sort methods for your arrays and get the results you expect.

 Published in:

- [  Front-end Development   ](/topics/frontend-development)
- [  JavaScript   ](/topics/javascript)

 

   You must have JavaScript enabled to use this form.

## Get in touch with us

### Tell us about your project. We'd love to hear from you!

 First Name  

 Last Name  

 Your email address  

 Your organization  

 How you heard about us  

 Tell us more 

     Leave this field blank