Sorting Arrays in JavaScript
Published at December 13, 2020.
JavaScript can be tricky sometimes. We know the times when we try something so easy like sorting an array, but it ends up so wrong and breaks our code.
When we know why this happens and how to fix it, it's all easy actually.
Array.prototype.sort()
In JavaScript, arrays have an useful sort
method and it can be used like this:
Just as we expected, right? It sorts the array in an ascending order.
Let's look at another example:
And welcome to lands of JavaScript! You can try this code snippet and see if the result is right or wrong. But it's absolutely right and there is a reason behind it.
The default method converts each of the elements to string
and then compares them. So, even if we try this on an array full of numeric values, it ends up like this.
The Compare Function
To make sort
method to act as we want, we need to give it a compare function. It's an optional parameter, but we saw how it executes if we don't pass it. The function should look like this:
Our compare
function should return a numeric value after comparing two items.
- If it returns 0, order of compared values does not change.
- If it returns a positive
number
,firstItem
gets placed aftersecondItem
. - If it returns a negative
number
,secondItem
gets placed afterfirstItem
.
So, if we want our numeric values to be sorted in an ascending order, we can do it like this:
And that's all we need to do! If we want to sort them in a descending order:
Sorting different data types
We saw how we can sort numeric values. But what about other things?
Date
Using the firstItem - secondItem
method is OK for Date
objects too. If our object has a valueOf
method that returns a numeric value and if it can indicate some sort of an order for that object, we can use this technique. For Date
, its valueOf
method returns number of milliseconds since the epoch (1970-01-01T00:00:00Z
). So, we can use it to sort Date
objects.
Or we can use getTime
method to be more explicit of course.
string
We know that sort
method implicitly converts items to string
and compares them. So, why do we think about string
values if we already have this? Let's have a look:
If we have numeric values in our strings and want to order items by considering them too, the default compare function is not enough for us.
For this case, we need to use Intl.Collator. It is a constructor that creates objects to be used in language sensitive string comparison.
Also, the same thing can be achieved by using localeCompare
too. It gets the same parameters as Intl.Collator
constructor.
As a side note, if we have a big array to sort, it's better to use Intl.Collator
in terms of performance.
Custom Objects
As we can see, we can compare items in an array as we want. So, comparing custom objects (or class instances etc.) are no different.
And we can use custom methods of our object, of course.
Array.prototype.sort()
Mutates the Original Array
Throughout our examples, you may have noticed something. We used sort
method a lot, but never assigned the value returned from it. Yep, you knew it. It mutates the original array. So if we use this method in a project built with a package that doesn't want you to mutate data (like React, React-Native, Redux etc.), we need to consider this too. Even though it returns the mutated array as a result like:
it mutates the original.
To handle this, we can do something like:
Conclusion
sort
is a very cool method of Array
class. When we know how it behaves on certain conditions, it's a really helpful method.
Thanks for reading!