2018-12-14
|~4 min read
|613 words
Javascript’s built-in sort is powerful and fast. However, there are many times when you will want to sort in a custom fashion.
Whenever I wanted to create a custom sort, I kept referring back to MDN’s great page on the .sort() method.
This post is intended as a complement to that and one that pulls out some of the critical points I needed in order to grok how custom sorts worked in my most common use cases.
Underpinning all of the sorting methods in Javascript are a few simple rules:
a
and b
> 0
means that the a
is greater than b
and will come after it== 0
means the values are equal and it does not matter which comes first< 0
means that a
is less than b
and will come before itconst arr = [4, 1, 2, 5, 3, 2]
function ascendingSort(a, b) {
if (a < b) {
return -1
}
return 1
}
function descendingSort(a, b) {
if (a < b) {
return 1
}
return -1
}
console.log(`Native --> `, arr.sort()) // [ 1, 2, 2, 3, 4, 5 ]
console.log(`Ascending -> `, arr.sort(ascendingSort)) // [ 1, 2, 2, 3, 4, 5 ]
console.log(`Descending -> `, arr.sort(descendingSort)) // [ 5, 4, 3, 2, 2, 1 ]
These same rules apply for a more complicated scenario. For example, let’s think about sorting an array where each element is itself an array.
The elements take the shape of [char, number]
, e.g., [a,2]
We want to sort in the following way:
const nestedArray = [
["m", 1],
["i", 4],
["s", 4],
["p", 2],
]
function descNumbersAscChar(arrA, arrB) {
if (arrA[1] > arrB[1]) {
return -1
} else if (arrA[1] === arrB[1]) {
if (arrA[0] < arrB[0]) {
return -1
} else if (arrA[0] > arrB[0]) {
return 1
}
} else if (arrA[1] < arrB[1]) {
return 1
} else {
console.log("Uncaught situation!")
return 1
}
}
console.log(nestedArray.sort(descNumbersAscChar)) // [ [ 'i', 4 ], [ 's', 4 ], [ 'p', 2 ], [ 'm', 1 ] ]
One of the reasons that this took a while for things to click is that I was thinking in terms of boolean comparisons.
This is actually what Javascript is doing, but because it doesn’t want to look at the conditional (that is a < b
), it relies on you to tell it what to do with a 1
and -1
.
If you still want to use Boolean logic, however, it’s fairly straightforward.
Refactoring the ascendingSort
function from earlier:
/**
* Boolean overview
* if (a < b) {
* // do this because it's true
* } else {
* // do this because it's false
* }
*/
const arr = [4,1,2,5,3,2];
function ascendingSortBool(a,b) {
return +(a > b) || -(a < b)
}
console.log(`Ascending -> `, .sort(ascendingSortBool)) // [ 1, 2, 2, 3, 4, 5 ]
This works because function returns 1
if b
and -1
if b < a
. This avoids the issue of a false returning 0
which the .sort()
wouldn’t do anything with.
Stackoverflow: Sorting in Javascript - credit to Bergi for the answer that really helped clarify my understanding on the topic
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!