DEV Community

cole-flournoy
cole-flournoy

Posted on • Updated on

Breaking Down Javascript Sort() And Sorting By Multiple Criteria

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:

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>)
Enter fullscreen mode Exit fullscreen mode

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.

const myBestFriends = ["Tom", "Jerry", "Popeye", "Brutus"]
myBestFriends.sort()
// => ["Brutus", "Jerry", "Popeye", "Tom"] 
Enter fullscreen mode Exit fullscreen mode

Nice, much better in alphabetical order. Same should go for numbers, right?

const luckyNumbers = [7, 64, 16, 44]
luckyNumbers.sort()
// => [16, 44, 64, 7]
Enter fullscreen mode Exit fullscreen mode

Nick Young Confused Meme

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 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:

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]
Enter fullscreen mode Exit fullscreen mode

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:

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"]
Enter fullscreen mode Exit fullscreen mode

And in case the ternary operator is throwing you off, these are also equivalent:

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"]
Enter fullscreen mode Exit fullscreen mode

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:

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}]
Enter fullscreen mode Exit fullscreen mode

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:

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"}]
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)