# Custom Array Sort Algorithms in JavaScript

%[https://www.youtube.com/watch?v=-S8b_j5XBV0]

## JavaScript's Default Array Sort

JavaScript's `Array.sort` defaults to a `String` sort. This catches many people off guard when attempting to sort an `Array` of type `Number`.

```javascript
// ❌ Default search is a String search
const numbers = [10, 1, 3, 15]
numbers.sort() // [ 1, 10, 15, 3 ]
```

In the above example, each `Number` is converted to a `String` and then sorted using a `String` sort.

At first, this can seem like a WTF JavaScript moment, but this happens because an `Array` can contain mixed elements and JavaScript doesn't know how it should sort. So `sort` defaults to a `String` sort.

```javascript
const array = [1, 2, 3, 'Joel', 4, { userId: 123 }]
```

When we want something other than a `String` sort, we have to be explicit.

## Custom Sort Compare Function

Creating a custom sort compare function is pretty easy. The function takes two elements, then we return `-1` if the first is lower and `1` if it's higher. `0` for the same.

```javascript
const compareFunction = (a, b) => {
    // Pseudo Code
    if (a is less than b) return -1
    if (a is more than b) return 1
    return 0
}
```

Then pass that function to the `sort` method.

```javascript
myArray.sort(compareFunction)
```

This flexibility will allow us to be creative with our sorting algorithms.

## Number Sort

To sort a `Number` `Array` we could create a custom `compareNumbers` function and pass that into `Array.sort`.

```javascript
const compareNumbers = (a, b) => a - b

const numbers = [10, 1, 3, 15]
numbers.sort(compareNumbers) // [ 1, 3, 10, 15 ]
```

## Custom Object Sort

Let's say we had some data that looks like this:

```javascript
const customers = [
	{ id: 1, orders: ['a-1000', 'x-2000', 'c-8000'] },
	{ id: 2, orders: ['a-1010'] },
	{ id: 3, orders: ['a-1040', 'c-8050'] },
]
```

Our requirement is to sort by the number (`length`) of `orders`. So the order should be `2`, `3`, `1`.

We can do that with a custom `compareOrderLength` function that will sort by `customer.orders.length`.

```javascript
const compareOrderLength = (a, b) => a.orders.length - b.orders.length

customers.sort(compareOrderLength)
/**
 * [
 *   { id: 2, orders: [ 'a-1010' ] }, 
 *   { id: 3, orders: [ 'a-1040', 'c-8050' ] }, 
 *   { id: 1, orders: [ 'a-1000', 'x-2000', 'c-8000' ] }
 * ]
 */
```

## Complex Custom Sorting

I recently had a use case where an API was returning data that looked like this. 

```javascript
// API Response
["1", "10", "2", "BLA", "BLA2", "3"]
```

The `Array` contained all `String` items, but the business wanted the items to display like "1, 2, 3, 10, BLA, BLA2".

That meant, I had to detect when the `String` was a `Number` and Sort the "numbers" first and the text after.

As complex as that sounds, the sort algorithm wasn't too bad.

```javascript
const isNumeric = (num) => !isNaN(num)

const customCompare = (a, b) => {
	if (isNumeric(a) && !isNumeric(b)) return -1
	if (!isNumeric(a) && isNumeric(b)) return 1
	if (isNumeric(a) && isNumeric(b)) return a - b
	return a < b ? -1 : 1
}

// [ '1', '2', '3', '10', 'BLA', 'BLA2' ]
```

## End

So just remember the default `Array` sort is a `String` sort. To sort by anything else, you must create a compare function and pass that into sort.

- Check out my 📰 [Newsletter](https://joel.net/newsletter)
- Subscribe to my 📺 YouTube, [JoelCodes](https://www.youtube.com/c/JoelCodes?sub_confirmation=1)
- Say hi to me on Twitter [@joelnet](https://twitter.com/joelnet)

Cheers 🍻

<span>[Photo](https://unsplash.com/photos/-nz-GTuvyBw) by <a href="https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Kelly Sikkema</a> on <a href="https://unsplash.com/s/photos/organize?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>
