sort() method that you can use on arrays, but the results are almost always weird and don’t return what you initially expect.
For example, if you have the following
[9, 8, 12, 1, 33, 21] array, using
sort() on it will return
[1, 12, 21, 33, 8, 9].
sort() method isn’t exactly what it makes itself out to be. The array returned is hardly sorted at all — or maybe it is, but just not in the way we want it to be.
sort() method converts each item in the array into strings and constructs the sequence by comparing each array item based on the UTF-16 code values when there is no callback specified.
How UTF-16 Works
sort()is used, it automatically calls the
String() cast method on every array element by default and turns everything into a string. It does this in order to ensure that things can be sorted in a uniform manner. It’s easier to sort when things are the same type.
UTF-16 stands for 16-bit Unicode Transformation Format. It’s the standardized form for translating bits into a format comprehensible to humans. It’s basically a translation table for a corresponding character.
sort(), you are essentially sorting against whatever order the characters are in for this table. That is why
33 came before
8 in the sorted array above. It is because the character
3 appears before
8 in the table. The sort is done based on character appearance rather than mathematical reasoning or rules.
sort() method isn’t wrong — it’s merely misunderstood.
How to Turn Numbers Into Numbers
sort() is used on its own, it returns values based on the order of things in the UTF-16 table. However,
sort() also takes a callback function that allows you to decide how things will appear.
This callback function takes two arguments —
b — for convention purposes. You use these arguments to create an equation that either returns 1, -1, or 0.
When the equation returns 1,
a gets to proceed. If the equation returns -1, then
b gets to proceed. If the equation equates to 0, then it means that both are equal in value and it is the end of the recursive sorting algorithm
sort() runs through.
So when you’re working with numbers and using the callback function, the
String() cast is not placed on the array items. This is because
sort() needs a callback comparator, and when
sort() is used without one,
String() acts as the default callback.
Let’s look at the code below:
This is our callback function that will help sort the numbers in the correct and ascending order. So when you want to sort an array of numbers, you can do so by doing something like this:
To inverse it, you can just inverse the logic of the code so it’s
b > a and
b < a.
What About (a, b) => a- b ?
In many tutorials and StackOverflow answers, you may have seen solutions that look something like this:
arrayNameHere.sort((a, b) => a - b);.
The thing with 1 and -1 is that it doesn’t have to be these two numbers specifically. It just needs to fall into one of the two spectrums of either being a positive or negative number.
sort() will still treat it the same way as the code example above.
0 is a definite number that signifies the end of the sorting recursion, so this is the only non-negotiable value.
This is why
(a, b) => a - b works. For example, if
a = 5 and
b = 2,
a - b results in a positive number, making
a the bigger number and returning the equivalent of 1.
It is good to note that this kind of sort logic only works with numeric types or objects that return numeric values when
valueOf() is used.
So algorithmically, for an array with three values, it looks something like this:
What About Non-Numeric Sorting Like Months?
For non-numerical sorting, you’ll need to get creative and think of a way to transform it into a numerical comparison in your callback function.
Remember that sort works on positive and negative numbers to determine the positioning of things. So when it comes to months, you can do something like this:
In the code above, we created a list that allows us to attach a numerical value, enabling us to create an order to the final results we want to emulate. By using
indexOf(), we are able to create the returned values required by
sort() in order to figure out the correct sequence of things.
sort() can be quite powerful when you understand how to use it. A lot of other examples tend to put their callback logic inside
sort() itself, but my personal preference is to make it a separate function so that it’s easier to understand and modularizes your code by creating reusability.
Imagine having to write the code inside
sortMonths over and over again in multiple places. It can get rather cumbersome. Or perhaps the logic gets complicated and you start to lose your brackets and braces in the process.
(a, b) => a - b might look short in the short term, but when the logic expands, things can get messy visually very quickly. This is just a side pointer to help make your code easier to work with for the long haul.
All in all, this is basically how
sort() works in a nutshell.
Thank you for reading.