Sorting arrays is a common operation that’s done in many apps. The sort
method that comes with JavaScript arrays makes this easy. However, there are lots of intricacies when it comes to sorting arrays.
In this article, we’ll look at how to sort arrays with the sort
method. Also, we’ll look at how to compare objects to order them in the way that we desire.
Basic Sorting
The most basic sorting operation is probably sorting numbers. With the sort
method, we can do this easily. For example, if we have the following array:
let arr = [3, 4, 5, 2, 5, 8, 9];
Then we can sort is with the sort
method as follows:
arr.sort();
The arr
array is sorted in place, so we don’t have to assign it to a new variable.
After calling sort
, we get that the array is:
[2, 3, 4, 5, 5, 8, 9]
We can see that the sorting is done by ordering numbers in ascending order.
Sorting number arrays in ascending order are the simplest cases. We didn’t have to modify the sort
method’s default functionality to do this.
We can also sort strings by ascending Unicode code point order. The sort
method will sort by the total code points of each string. The full list of code points for Unicode characters are listed at https://en.wikipedia.org/wiki/List_of_Unicode_characters.
For example, given the following array:
let strings = ['foo', 'bar', 'baz'];
We can call sort
by writing:
strings.sort();
to sort in ascending total Unicode code points.
Copying an Array Before Sorting
As we can see, sort
will sort the array it’s called on in place. We can avoid this by copying the array to a new array before sorting.
To do this, we can either use the slice
method as follows:
let sortedStrings = strings.slice().sort();
Or more conveniently, we can use the spread operator to do the same thing:
let sortedStrings = [...strings].sort();
Sorting with Compare Functions
The sort
method can take an optional callback function to let us compare the content of the array to let us sort it the way we want.
The callback function takes 2 arguments. The first one is the array entry that comes first, the second is the one that comes after the one in the first argument.
We compare them and then return a positive number, negative number, or 0 depending on our preference.
Given that we have 2 entries, a
and b
for the first and second parameter for the callback respectively, we return a negative number to make a
come before b
. To make b
come before a
we can return a positive number.
To keep their order unchanged with respect to each other, we return 0.
For example, we can use this to sort numbers in reverse as follows:
arr.sort((a, b) => b - a);
We want to make the bigger entry come before the smaller entry, so we return b — a
to make b
come before a
if b
is bigger than a
since b
bigger than a
means that b — a
will be positive.
Otherwise, if b
is smaller than a
, it’ll be negative, and it’ll be zero if they’re the same.
It’s also handy for sorting by fields in an array of objects. If we want to sort by a field of objects, then we’ve to write a compare function to do it. For example, given the following array:
let arr = [{
name: 'Joe',
age: 20
},
{
name: 'Mary',
age: 16
},
{
name: 'Jane',
age: 22
},
];
We can sort by the age
field by ascending age as follows:
arr.sort((a, b) => a.age - b.age);
It works the same as sorting other numbers. If a.age
is less than b.age
, then we return a negative number, so a
comes before b
. If it’s the reverse, then b
comes before a
, where a
and b
are neighboring entries of the array.
Otherwise, if they’re the same, then a
and b
’s order stays the same.
Then we get the following if we log the array:
{name: "Mary", age: 16}
{name: "Joe", age: 20}
{name: "Jane", age: 22}
We can use the comparison operators like >
, <
, <=
, or >=
to compare strings.
For example, if we want to sort the array above by name, we can write:
arr.sort((a, b) => {
if (a.name.toLowerCase() < b.name.toLowerCase()) {
return -1;
} else if (a.name.toLowerCase() > b.name.toLowerCase()) {
return 1;
}
return 0;
});
Then we get the following result:
{name: "Jane", age: 22}
{name: "Joe", age: 20}
{name: "Mary", age: 16}
Comparing Non-English Strings
The callback for sorting strings above works great sorting English strings. However, it doesn’t work very well for non-English strings since it doesn’t take into account things like punctuation or accents.
To compare these kinds of strings, we can use the localeCompare
method that comes with strings.
It has lots of optional that we can adjust for changing the comparison of strings, like whether to check accents, case, and other variants of a letter. The locale for comparison can also be adjusted.
The full list of options are at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
We can use it as follows:
let arr = ['réservé', 'Premier', 'Cliché', 'communiqué', 'café', 'Adieu'];
arr.sort((a, b) => a.localeCompare(b, 'fr', {
ignorePunctuation: true,
sensitivity: 'base'
}));
In the code above, we passed a string b
to compare with a
in the comparison function of the localeCompare
method as the first argument. Then we set the second argument to the 'fr'
locale to indicate that we’re comparing French string. Finally, we passed in some basic options, which include ignoring punctuation and adjusting the sensitivity of the string comparison.
sensitivity
set to 'base'
means that strings that differ in letters are unequal.
After the sort
method call above, we get that the value for arr
is:
["Adieu", "café", "Cliché", "communiqué", "Premier", "réservé"]
Sorting JavaScript arrays have its tricky parts. The easiest case is sorting numbers and string code points in ascending order, which requires no comparison function.
For more complex comparisons, we’ve to pass in a comparison function. In it, returning a negative number will make the first value come before the second. Positive will make the second value come before the first. Returning 0 will keep the existing order.
Comparing non-English strings requires more care. We can use the localeCompare
method that comes with strings to do the comparison by passing in various options.