Arrays always come in handy when writing any piece of Javascript code. You can use them to hold a list of items either as objects, strings, numbers, or a mix of both strings and numbers. Similar to other programming languages, the Array object in Javascript supports a variety of methods. They include: pop(), push(), toString(), join(), sort() etc. This post will focus on the Array.sort() method.

The Array Sort() method sorts the elements of an array using a numerical, alphabetical, or custom order. The default sort order is ascending order which sorts the elements starting with the smallest value first and the most significant value last. The regular sort() method works by converting the elements in the Array to strings and comparing the sequences of their UTF-16 code unit values.

Some of this information might sound confusing, but it’s necessary, especially when dealing with an array of numbers. This post will give you a master guide on using the Array Sort method in JavaScript.

Array Sort() Syntax

The general syntax of the Array Sort() method is:

//Function-less expression
arr.sort()

//Function expression
arr.sort(function CompareFn(a, b) { /* ... */ } )

//Using paremeters - the compare function
arr.sort(compareFn)

//Arrow function expression
arr.sort((a, b) => { /* ... */ })

Where arr is the name of our Array.

One thing you need to note when working with the sort method is that it manipulates the Array of elements’ in place.’ It does not make a copy of the Array and instead sorts the original Array. After sorting, the Array Sort method returns a reference to the original Array, which is now sorted.

The code below will give you a better understanding of what we mean.

let myArr = [1,5,6,4,7,9,3,8,2]
console.log(myArr)
//returns [ 1, 5, 6, 4, 7, 9, 3, 8, 2 ]
myArr.sort()
console.log(myArr)
//Output: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

The sort() method in the code above did not make a new array. It sorted our original Array (myArr). That is an important distinction to note because when working with other Array methods like filter() and map(), you will notice that these two methods will make a new copy of the Array.

Array Sort Examples | The Issue With the Standard Lexicographic Ordering

When you start using the Array sort() method, it might get a little confusing along the way because of how it is designed to sort elements. Let’s look at a few examples and see what we are talking about here.

//Sorting an array of numbers

let arrOne = [6,3,5,4,1,2]
arrOne.sort()
console.log(arrOne)
//Output: [1,2,3,4,5,6]

Everything looks fine in the code above. We have an array of numbers, and after sorting, the resulting output had the numbers arranged in ascending order as expected.

But there is a catch! Let’s try using an array that has a mix of single-digit and two-digit numbers.

//Sorting an array of numbers (a mix of one-digit and two-digits)

let arrOne = [6,3,5,23,4,1,2,10,15]
arrOne.sort()
console.log(arrOne)
//Output: [ 1, 10, 15, 2, 23, 3, 4, 5, 6 ]

What’s happening? If the sort() method sorts array elements in ascending order, then 10, 15, and 23 would be the last digits in the output. But that’s not what we are getting in the array result. The reason is that the sort() method converts all elements to strings before sorting.

Let’s look at another example where we have strings as the elements in the Array.

//Sorting Strings

let arrOne = ["hello","a","b", "my","c","name"]
arrOne.sort()
console.log(arrOne)
//Output: [ 'a', 'b', 'c', 'hello', 'my', 'name' ]

Everything looks fine, and the output consists of elements sorted in ascending alphabetical order. Now, what if we used an array of mixed case characters? Let’s see what happens.

//Sorting an array of strings (a mix of small and capital letters)

let arrOne = ["a","b","A","c","B","C","Hello","Zebra"]
arrOne.sort()
console.log(arrOne)
//Output: [ 'A', 'B', 'C', 'Hello', 'Zebra', 'a', 'b', 'c' ]

Here, we notice that the sort() method sorted the Array with the capital letters first and the small letters last. That’s why names like ‘Hello‘ and ‘Zebra‘ come before ‘a,’ ‘b,’ and ‘c.’ Let’s look at another example: an array of mixed numbers and strings.

let arrOne = ["d","b","1","c","2","a","4","3","hello"]
arrOne.sort()
console.log(arrOne)
//Output: [ '1', '2', '3', '4', 'a', 'b', 'c', 'd', 'hello' ]

Here, we notice that the sort() method sorts the elements with numbers followed by strings in ascending order. Lastly, let’s try sorting an array of objects.

let arrOne =[
{name:"John",age:23,},
{name:"Jane",age:22,}]
arrOne.sort()
console.log(arrOne)
//Output: [ { name: 'John', age: 23 }, { name: 'Jane', age: 22 } ]

Well, from the results in the code above, nothing changed after using the sort() method on an array of objects.

What’s the Solution?

From all the examples we have looked at above, you have probably noticed there is a default method (Lexicographic Ordering) that the sort() method uses to sort obvious things like numbers and strings. So, how do we fix that and solve all the issues we saw in the above examples?

We will need to devise a way that we can use to sort elements ourselves instead of the default sorting method available in Javascript. That brings us to the Compare Function.

The Compare Function

The Compare function allows you to use an alternative sorting order different from the default method provided by the sort() method. Without the compare function, the sort() method converts the elements in an array to strings and then compares them by their UTF-16 code units order.

Let’s look at the general Compare function syntax.

function compare(a,b){
return a - b
}

The compare function should only return a negative value, a positive value, or a zero depending on the values provided. These returned values determine in what order the sort() method will sort the Array.

  • If the return value is > 0 (positive value), ‘a’ will be sorted after ‘b.’ That means ‘a’ is larger than ‘b‘ and ‘b‘ comes first.
  • If the return value is < 0 (negative value), ‘b‘ will be sorted after ‘a.’ That means ‘b‘ is larger than ‘a’ and ‘a’ comes first.
  • If the return value is === 0 (equal to zero) nothing will change. Both ‘a’ and ‘b‘ will keep their original order.

To explain the information above in code, this is another way we can write the Compare function.

function(a, b) {
    if (a > b) return 1;
    if (a < b) return -1;
    /* else */ return 0;
}

Now that you understand how we can use the Compare function in our sort() method, you might have questions like: What is the principle of choosing a and b? What logic does the compare function use for comparison?

How Does the Compare Function Work?

To have a better understanding, take the Array of numbers below. Here, we use the compare function to sort the elements in descending order.

let arr = [5, 2, 1, -10, 8];

arr.sort(function(a, b) {
  console.log(a,b)
  return b - a;
});
console.log("The sorted array: "+ arr)

Output:

5 2
2 1
1 -10
-10 8
1 8
2 8
5 8
The sorted array: 8,5,2,1,-10

The final output shows that we successfully sorted the array in descending order. However, we will focus on the other logged result to understand how the Compare function works.

The working of the compare function entirely depends on the implementation. In this example, it goes from index zero to the end, and if a swap has not occurred at the last two items, it stops; otherwise, it moves back to index zero. However, the number of elements and the browser can also be a determiner.

It tests and changes in this order:

5   2   1 -10   8   original order
5   2
    2   1
        1 -10
          -10   8   swap
            8 -10
        1   8       swap
        8   1
    2   8           swap
    8   2
5   8               swap
8   5  2    1 -10   result

Now that you clearly understand the Sort method and the Compare function let’s look at several examples where it’s applicable.

Tip: From this point, we will write the Compare function as an arrow function. Arrow functions have the advantage of having shorter syntax and require less code.

Sorting an Array of Single Digit Numbers

Suppose we have an array of single digits:

let nums = [5,4,6,1,3,2]

To sort this Array in ascending order, you don’t need the compare function. Use the sort method as shown in the code below.

nums.sort()
console.log(nums)
//Output: [ 1, 2, 3, 4, 5, 6 ]

We will need a compare function to sort the Array in descending order.

nums.sort((a,b)=>{
return b - a
})
console.log(nums)
//Output: [ 6, 5, 4, 3, 2, 1 ]

Sorting an Array of Double-Digit Numbers

Suppose we have an array of both single and double digits.

const marks = [50, 100, 10, 45, 25, 20, 2, 5];

We will need to use a compare function to sort such an array (whether in ascending or descending order).

//Without the compare function
marks.sort()
console.log(marks)
//Output: [ 10, 100, 2, 20, 25, 45, 5, 50 ]

Let’s use a compare function to sort the elements in ascending order.


marks.sort(function(a, b){
return a-b
});
console.log(marks)
//Output: [ 2, 5, 10, 20, 25, 45, 50, 100 ]

We only reverse the compare function to sort the Array in descending order.

marks.sort(function(a, b){
return b - a
});
console.log(marks)
//Output: [ 100, 50, 45, 25, 20, 10, 5, 2 ]

When we look at the examples above, we can see the difference in results between using the sort() method alone and passing the compare function to the sort method.

Sorting an Array of Strings Alphabetically

Suppose we have an array of animals.

let animals = [
"elephant","antelope","buffalo","hyena","zebra","cat"
]

To sort this alphabetically Array in ascending order, we don’t need to pass the Compare function. We will use the regular sort() method.

animals.sort()
console.log(animals)
//Output: [ 'antelope', 'buffalo', 'cat', 'elephant', 'hyena', 'zebra' ]

To sort the Array alphabetically in descending order, we would need to use a Compare function and change the default sorting logic.

Tip: Since we are dealing with strings, we cannot use the usual (a – b) in our Compare function as that return a NaN value. We will compare the values using greater than (>) and less than (<) signs.

animals.sort((a,b)=>{
    if (a > b) return -1;
    if (a < b) return 1;
           return 0;})
console.log(animals)
//Output: [ 'zebra', 'hyena', 'elephant', 'cat', 'buffalo', 'antelope' ]

Although the code above worked as expected, we can make it shorter and more neat using the ternary operator.

let animals = ["elephant","antelope","buffalo","hyena","zebra","cat"];
animals.sort((a, b) => (a > b ? -1 : 1));
console.log(animals)
//Output: [ 'zebra', 'hyena', 'elephant', 'cat', 'buffalo', 'antelope' ]

Sorting an Array of Mixed Case Strings

Suppose we had an array of mixed-case elements.

let alphabets = [
"B","c","a","D","A","d","e"
]

If we sort this Array without passing a Compare function, the uppercase letters will come first, followed by lowercase characters in ascending order.

alphabets.sort()
console.log(alphabets)
//Output: [ 'A', 'B', 'D', 'a', 'c', 'd', 'e' ]

However, that’s not what we need. We will use simple logic to solve this issue. Create a compare function that first converts all elements to uppercase before sorting.

Tip: here, we are sorting the elements in ascending order.

alphabets.sort( (a, b) =>{
    let x = a.toUpperCase(),
        y = b.toUpperCase();
    return x == y ? 0 : x > y ? 1 : -1;
});
console.log(alphabets)
//Output: [ 'a', 'A', 'B', 'c', 'D', 'd', 'e' ]

To sort the ‘alphabets’ Array in descending order, we will need to change the logic in our Compare function, as shown below.

return x == y ? 0 : x > y ? -1 : 1;
console.log(alphabets)
//Output: [ 'e', 'D', 'd', 'c', 'B', 'a', 'A' ]

Sorting an Array of Strings by Length

Suppose you want to sort an array of strings by comparing their length. Take an example of an array of random words.

let arr = [
"you","went","to","Mexico","yesterday"
]

We will write a compare function that compares the strings by their length.

arr.sort((a,b) => {
return (a.length - b.length)
})
console.log(arr)
//Output: [ 'to', 'you', 'went', 'Mexico', 'yesterday' ]

Sorting an array of strings with non-ASCII characters

All the previous examples we have looked at when working with strings use ASCII characters. Suppose we have an array of non-ASCII characters like é, è, À, È, Ì, Ò, Ù, etc.

let animals = [
'zèbre', 'abeille', 'écureuil', 'chat'
]

Let’s try sorting the Array with the regular sort() method.

animals.sort()
console.log(animals)
//Output: [ 'abeille', 'chat', 'zèbre', 'écureuil' ]

We have a problem. ‘écureuil‘ should come before ‘zèbre.’ To solve that, we will need to use the localCompare() method inside our Compare function. The localCompare method compares strings by their specific locale. Here, we are sorting the elements in ascending order.

animals.sort((a,b) => {
    return a.localeCompare(b);
})
console.log(animals)
//Output: [ 'abeille', 'chat', 'écureuil', 'zèbre' ]

To sort the elements in descending order, we will reverse our localCompare method.

animals.sort((a,b) => {
    return b.localeCompare(a);
})
console.log(animals)
//Output: [ 'zèbre', 'écureuil', 'chat', 'abeille' ]

Sorting an Array of Objects by Numeric Property

Let’s take an array of objects as shown in the code below.

let arr=[
{name:"Jane", age:24, points:16},
{name:"Jack", age:20, points:30},
{name:"John", age:28, points:18}
]

Tip: We will sort the elements using their ‘age’ in ascending order.

//Let's write our Compare function here
function compareFn(a,b){
    return (a.age - b.age)
}
arr.sort(compareFn) //Here, we call the Compare function inside the Sort method
console.log(arr)
//Output:
//[ { name: 'Jack', age: 20, points: 30 },
//  { name: 'Jane', age: 24, points: 16 },
//  { name: 'John', age: 28, points: 18 } ]

From the results above, we can see we successfully sorted the array in ascending order, with Jack (age 20) being the first and John (age 28) last.

But we can shorten the code above and make it neat using arrow functions as shown below.

arr.sort((a,b) =>{return a.age - b.age})
console.log(arr)
//Output:
//[ { name: 'Jack', age: 20, points: 30 },
//  { name: 'Jane', age: 24, points: 16 },
//  { name: 'John', age: 28, points: 18 } ]

We are still getting the same results. The elements were sorted using their ‘age‘ and arranged in ascending order.

What if we wanted to arrange them in descending order? Then, we need to reverse our Compare function.

arr.sort((a,b) =>{return b.age - a.age})
console.log(arr)
//Output:
//[ { name: 'John', age: 28, points: 18 },
//  { name: 'Jane', age: 24, points: 16 },
//  { name: 'Jack', age: 20, points: 30 } ]

Sorting an Array of Objects by String Property

To sort objects by a string property, we need to convert the strings to a single case (say uppercase or lowercase) before sorting. Suppose we have an array of tech company objects, as shown below.

let arr=[
{name:"Google", founded:1998},
{name:"HP", founded:1939},
{name:"Dell", founded:1984}
{name:"Apple", founded:1976}]

Let’s sort the elements by their “names” in ascending order.

//Compare Function
arr.sort((a,b) => {
    let x = a.name.toUpperCase(),
        y = b.name.toUpperCase();
    return x == y ? 0 : x > y ? 1 : -1;
})
console.log(arr)
//Output: 
//[ { name: 'Apple', founded: 1976 },
//  { name: 'Dell', founded: 1984 },
//  { name: 'Google', founded: 1998 },
//  { name: 'HP', founded: 1939 } ]

We simply reverse our compare function to sort the elements in descending order.

arr.sort((a,b) => {
    let x = a.name.toUpperCase(),
        y = b.name.toUpperCase();
    return x == y ? 0 : x > y ? -1 : 1;
})
console.log(arr)
//Output:
//[ { name: 'HP', founded: 1939 },
//  { name: 'Google', founded: 1998 },
//  { name: 'Dell', founded: 1984 },
//  { name: 'Apple', founded: 1976 } ]

Optimizing the Sort Method using Map()

When we looked at “How Does the Compare Function Work?” we noticed that the compare function is invoked multiple times on certain elements of an array. That might impact application performance, especially when dealing with huge amounts of data.

We might not effectively reduce the time the compare function is invoked, but we can optimize the comparison part.

We can achieve that using the Map() method in three simple steps.

  • First, we extract the actual values we need to sort from the original Array to a temporary array using the map() method.
  • Sort the temporary Array, which now contains the already evaluated values.
  • Traverse the sorted temporary Array to copy the sorted elements into the original Array.

Let’s use the code below to have a better understanding.

let originalArr = ["you","went","to","Mexico","yesterday"];
//Create a temporary array that will hold element index and length
let tempArr = originalArr.map(function (e, i) {
    return {index: i, value: e.length };
});
// Let's sort the temporary array
tempArr.sort(function (a, b) {
    return a.value == b.value ? 0 : a.value > b.value ? 1 : -1;
});
// Copy the elements back to the original array
let finalArr = tempArr.map(function (e) {
    return originalArr[e.index];
});
console.log(finalArr);
//Output: ['to', 'you', 'went', 'Mexico', 'yesterday']

Conclusion

This post has given you a comprehensive guide on the Javascript Array sort() method and how you can use it to sort an array of strings, objects, and numbers. We have also looked at the compare function, which allows you to use an alternative sorting order different from the default method provided by the sort() method.

Did this article help you understand how to use the Array Sort() method in JavaScript?

Let us know by replying on Twitter of Become A Better Programmer or to my personal Twitter account.

Author