Breaking Down Javascript Sort() And Sorting By Multiple Criteria
Tags: javascript, webdev, programming
Published: 2021-06-07 21:20:21

First off, let's take a look at the `Array.sort()` method and see how it works. `sort()` takes in a callback function with two arguments and iterates over the array, using those two arguments as placeholders for each element and the element after it. Then, in the body of the callback function, it makes a comparison between the two, moving the element forward or backward in the array according to the logic of that comparison. 

Yikes, that sounds way more complicated in English... How about we just look at some code. Here's a prototype:  

```javascript
Array.sort(function(currentElement, nextElement) {
    return <sortingLogic> 
    // e.g. currentElement - nextElement returns numerical Array in ascending order
}

// OR with ES6 arrow function (preferable)
Array.sort((currentElement, nextElement) => <sortingLogic>)
```
It compares Array[0] to Array[1], moves Array[1] forward or backward according to the logic of your condition, then starts over, comparing Array[1] to Array[2], and so on.

**Note:** _You'll commonly see `currentElement` and `nextElement` referred to as `a` and `b` respectively in most documentation, so that's what I'll be using. But you're declaring the function, so call it whatever you want._

  
By default, `sort()` assumes ascending order, and for simple arrays of _strings_ you have the option to call it without any callback function.

```javascript
const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort()
// => ["Brutus", "Jerry", "Popeye", "Tom"] 
``` 
Nice, much better in alphabetical order. Same should go for numbers, right?

```javascript
const luckyNumbers = [7, 64, 16, 44]
luckyNumbers.sort()
// => [16, 44, 64, 7]
```
![Nick Young Confused Meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6tyieczkaas9mseyj1b.png)

Ok, well that doesn't look right. Turns out, `sort()` by default compares array elements by turning them into strings and comparing their sequences of [UTF-16 code](https://en.wikipedia.org/wiki/UTF-16#Description) units values. What that means exactly is outside the scope of this article, but what you need to know is this: 

**If you are sorting numbers in Javascript, always pass a callback function! `7 < 64` returns `true` but `"7" < "64"` returns `false`**

Fortunately, we can still get the desired result from another one-liner:
```javascript
const luckyNumbers = [7, 64, 16, 44]
luckyNumbers.sort((a, b) => a - b) // ascending
// => [7, 16, 44, 64]
 ---
const luckyNumbers = [7, 64, 16, 44]
luckyNumbers.sort((a, b) => b - a) // descending
// => [64, 44, 16, 7]
```
**Note:** _`sort()` is a **destructive** method, meaning that the original array itself is being replaced with the sorted version. If you need to continue to use your original array, make sure to save the sorted array in a new variable - e.g. `let sortedNums = luckyNumbers.sort((a, b) => a - b)`_

The last thing to cover before sorting by multiple criteria is what the default `sort` method is doing behind the scenes when we call something like `myBestFriends.sort()`. These two are equivalent:  
```javascript
const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort()
// => ["Brutus", "Jerry", "Popeye", "Tom"] 

const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort((a, b) => a > b ? 1 : -1)
// => ["Brutus", "Jerry", "Popeye", "Tom"]
``` 
And in case the [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) is throwing you off, these are also equivalent:

```javascript
const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort((a, b) => a > b ? 1 : -1)
// => ["Brutus", "Jerry", "Popeye", "Tom"]

const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort((a, b) => {
    if (a > b){
        return 1
    } else{
        return -1
    }
// => ["Brutus", "Jerry", "Popeye", "Tom"]
```
We return 1 if the element needs to be moved up the array, -1 if it needs to move down, and don't do anything if the elements are the same (they stay where they are). 

### Multiple Criteria

So now that we understand how it works with simple arrays, we can easily extend that out to more complex structures. All we have to do is combine the pieces above in whatever way fits our use case. For example, in a win / loss column:

```javascript
const teams = [
    {name: "Bruins", wins: 32, losses: 20},
    {name: "Islanders", wins: 32, losses: 18},
    {name: "Capitals", wins: 33, losses: 19},
    {name: "Penguins", wins: 33, losses: 13}
]
teams.sort((a, b) => a.wins === b.wins ? a.losses - b.losses : b.wins - a.wins)

// => [{name: "Penguins", wins: 33, losses: 13}, 
//     {name: "Capitals", wins: 33, losses: 19},
//     {name: "Islanders", wins: 32, losses: 18},
//     {name: "Bruins", wins: 32, losses: 20}]
```
We're prioritizing wins over losses in descending order (more wins on top makes the most sense) as our default, but if the two teams have the same number of wins, we're then sorting losses in ascending order.  

Or say we have a list of our favorite Steves:

```javascript
const steves = [
    {first: "Steve", last: "Harvey"},
    {first: "Steven", last: "Spielberg"},
    {first: "Stephen", last: "Colbert"},
    {first: "Steve", last: "Carell"}
]
steves.sort( (a, b) => {
    if (a.first > b.first){return 1}
    if (a.first < b.first){return -1}
    if (a.last > b.last){return 1}
    if (a.last < b.last){return -1}
})

// => [{first: "Stephen", last: "Colbert"},
//     {first: "Steve", last: "Carell"},
//     {first: "Steve", last: "Harvey"},
//     {first: "Steven", last: "Spielberg"}]
```

This one looks a little weirder with all the if statements, but we don't actually ever have to check whether the values for our primary criterion -`first`- are the same (as we did in the previous example). If they are, the first two `if` statements will be ignored. 

You can see how through this process we could continue to add on additional criteria to sort in whatever quantity and order we wish with more and more conditional statements. Hopefully this has helped demystify `sort()` and how to use it.