DEV Community

Cover image for Top 7 JavaScript Array sort() Method Use Cases
Palash Mondal
Palash Mondal

Posted on • Updated on <time datetime="2021-09-04T05:25:17Z" class="date-no-year">Sep 4</time> • Originally published at iampalash.hashnode.dev

Top 7 JavaScript Array sort() Method Use Cases

Hi Everyone 👋

Today I wanted to share some of the most common use cases for Array sort() method in JavaScript. The sort() method sorts the elements of an array and returns the sorted array, and no copy is made. The default sort order is ascending. In this article, we will see how we can utilise its power to the fullest. 🚀

Let's start!


Table of Contents


1. Sort an Array of Strings

Ascending (A to Z):

We can sort a simple array of strings using a functionless array sort() method like this:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'Cherries'];
fruits.sort();    // 👈 default sort

console.log( fruits );
// ["Apples", "Bananas", "Cherries", "Watermelon"]
// A → B → C → W
Enter fullscreen mode Exit fullscreen mode

Descending (Z to A):

To sort the array of strings in descending order we can use String localeCompare() method like this:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'Cherries'];
fruits.sort((a, b) => b.localeCompare(a));

console.log( fruits );
// ["Watermelon", "Cherries", "Bananas", "Apples"]
// W → C → B → A
Enter fullscreen mode Exit fullscreen mode

Back to top


2. Case-insensitive Sort an Array of Strings

Issue:

Let us first see what happens when we do a default sort for an array containing both lowercase and uppercase string elements.

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort(); 

console.log( fruits );
// ["Apples", "Bananas", "Watermelon", "cherries"]
// A → B → W → c
Enter fullscreen mode Exit fullscreen mode

As you can see above output, with default sorting word Watermelon starting with a uppercase W is coming before cherries starting with a lowercase c. This happens because strings are sorted according to each character's Unicode code point value. Using string charCodeAt() we can get the UTF-16 code unit for each character and then see that:

'C'.charCodeAt()   // 67
'W'.charCodeAt()   // 87
'c'.charCodeAt()   // 99

// 67 < 87 < 99
// C → W → c
Enter fullscreen mode Exit fullscreen mode

Ascending (aA to zZ):

Using case-insensitive sorting we can make sure that we get a properly sorted array, no matter what the casing for each string element in the array is:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); 

console.log( fruits );
// ["Apples", "Bananas", "cherries", "Watermelon"]
// A → B → c → W 
Enter fullscreen mode Exit fullscreen mode

Or,

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' })); 

console.log( fruits );
// ["Apples", "Bananas", "cherries", "Watermelon"]
Enter fullscreen mode Exit fullscreen mode

Descending (zZ to aA):

For case-insensitive sorting of array of strings in descending order we can simply interchange a & b element in the sorting compare function like this:

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase())); 

console.log( fruits );
// ["Watermelon", "cherries", "Bananas", "Apples"]
// W → c → B → A 
Enter fullscreen mode Exit fullscreen mode

Or,

let fruits = ['Apples', 'Watermelon', 'Bananas', 'cherries'];
fruits.sort((a, b) => b.localeCompare(a, 'en', { sensitivity: 'base' })); 

console.log( fruits );
//  ["Apples", "Bananas", "cherries", "Watermelon"]
Enter fullscreen mode Exit fullscreen mode

Back to top


3. Sort an Array of Numbers

Issue:

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort();    // 👈 default sort

console.log( numbers );
//  [1, 10, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

In the above example, we can see that if we use a default sort on the numbers array we are getting an incorrect output as 10 is coming before 2 when it should be at the last position. This happens because array elements are sorted by converting them to strings and comparing strings in UTF-16 code units order. Thus in a numeric sort, 2 should come before 10, but because numbers are converted to strings, "10" comes before "2" in the Unicode order.

Ascending:

We can sort an array of numbers in ascending order using a simple compare function like this

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort((a, b) => a - b);   // 👈 compare function, simply return a - b

console.log( numbers );
// [1, 2, 3, 4, 5, 10]
Enter fullscreen mode Exit fullscreen mode

Descending:

To sort an array of numbers in descending order we can simply interchange a & b elements in the sorting compare function like this:

let numbers = [4, 2, 5, 1, 3, 10];
numbers.sort((a, b) => b - a);   // 👈 interchange `a` & `b` and return b - a

console.log( numbers );
// [10, 5, 4, 3, 2, 1]
Enter fullscreen mode Exit fullscreen mode

Back to top


4. Sort an Array of Date Strings

Issue:

// Date string in YYYY-MM-D format
let dates = [
  '2021-08-1',
  '2021-08-4',
  '2021-08-10',
  '2021-08-2'
];
dates.sort()    // 👈 default sort

console.log( dates )
// ["2021-08-1", "2021-08-10", "2021-08-2", "2021-08-4"]
Enter fullscreen mode Exit fullscreen mode

In the above example, we can see that the date string "2021-08-10" is coming before "2021-08-2" which is not the expected output. It happens because of the same reason when sorting number array, where we found that 10 was coming before 2 when using default sorting.

Ascending:

To properly sort an array of date strings we can create a Date object by passing the date string to a new Date() inside the compare function like this:

let dates = [ '2021-08-1', '2021-08-4', '2021-08-10', '2021-08-2' ];
dates.sort((a, b) => new Date(a) - new Date(b))  // 👈 using `Date` constructor here

console.log( dates )
// ["2021-08-1", "2021-08-2", "2021-08-4", "2021-08-10"]
Enter fullscreen mode Exit fullscreen mode

Descending:

For descending order we can simply interchange a & b elements in the sorting compare function like this:

let dates = [ '2021-08-1', '2021-08-4', '2021-08-10', '2021-08-2' ];
dates.sort((a, b) => new Date(b) - new Date(a))  // 👈  here

console.log( dates )
// ["2021-08-10", "2021-08-4", "2021-08-2", "2021-08-1"]
Enter fullscreen mode Exit fullscreen mode

Back to top


5. Sort an Array except for one Element

Let say we have a simple array like this

let fruits = ['Select', 'Apples', 'Watermelon', 'Bananas', 'Cherries'];
Enter fullscreen mode Exit fullscreen mode

and we want to sort all elements in this array, except "Select". So, no matter if we are sorting the array in ascending/descending order we should always have "Select" at the first position. For this simple demo, we are assuming there are no duplicates in this array and each element starts with an uppercase and the rest of the letters are in lowercase. So we are not doing any case-insensitive sorting just to keep things simple.

Ascending:

We can do this in ascending order by adding a little bit of extra logic to the sort compare function like this:

let fruits = ['Select', 'Apples', 'Watermelon', 'Bananas', 'Cherries'];

fruits.sort((a, b) => {

  // If the first element value is "Select",
  // then keep it before second element. a < b
  if (a === 'Select') return -1;

  // If second element value is "Select",
  // then keep it before first element. a > b
  if (b === 'Select') return 1;

  // Else default sorting of string
  return a.localeCompare(b);
});

console.log( fruits )
// ["Select", "Apples", "Bananas", "Cherries", "Watermelon"]
// ↑ "Select" is at the first position and rest of the element is sorted
Enter fullscreen mode Exit fullscreen mode

Descending:

For descending order logic we just need to interchange a & b for the localeCompare logic and we get the desired output.

let fruits = ['Select', 'Apples', 'Watermelon', 'Bananas', 'Cherries'];

fruits.sort((a, b) => {
  if (a === 'Select') return -1; 
  if (b === 'Select') return 1;

  return b.localeCompare(a);  // 👈 interchange `a` & `b` here
});

console.log( fruits )
// ["Select", "Watermelon", "Cherries", "Bananas", "Apples"]
// ↑ "Select" is still at the first position and rest of the element is sorted
Enter fullscreen mode Exit fullscreen mode

Back to top


6. Sort Array of Objects by Property Value

Ascending:

We can sort an array of objects by a property value like this:

let inventory = [
  {name: 'Bananas', quantity: 5},
  {name: 'Apples',  quantity: 10},
  {name: 'Grapes',  quantity: 2}
];

// Sort by the "quantity" property value
inventory.sort((a, b) => a.quantity - b.quantity);  // 👈 here

console.log( inventory )
// Output
/*
[
  { "name": "Grapes",  "quantity": 2 },
  { "name": "Bananas", "quantity": 5 },
  { "name": "Apples",  "quantity": 10 }
]
*/
Enter fullscreen mode Exit fullscreen mode

Now we can see that in the above array after sorting in ascending order, the object with name property value "Grapes" is coming first as its quantity value is lowest 2, then we have an object with quantity value 5 and then 10.

Descending:

For descending order logic we just need to interchange a & b in the sort compare function like:

let inventory = [
  {name: 'Bananas', quantity: 5},
  {name: 'Apples',  quantity: 10},
  {name: 'Grapes',  quantity: 2}
];

// Sort by the "quantity" property value
inventory.sort((a, b) => b.quantity - a.quantity);  // 👈 interchange `a` & `b` here

console.log( inventory )
// Output
/*
[
  { "name": "Apples",  "quantity": 10 },
  { "name": "Bananas", "quantity": 5 },
  { "name": "Grapes",  "quantity": 2 }
]
*/
Enter fullscreen mode Exit fullscreen mode

Back to top


7. Sort Array of Objects by Multiple Property values

Ascending:

Let say we have an array like this:

let inventory = [
  {name:"Bananas", color:"Yellow", quantity:5},
  {name:"Apples", color:"Red", quantity:4},
  {name:"Apples", color:"Green", quantity:10},
  {name:"Grapes", color:"Green", quantity:2},
  {name:"Apples", color:"Yellow", quantity:6}
];
Enter fullscreen mode Exit fullscreen mode

Our requirement is:

  1. First, we need to sort the name property values in ascending order.
  2. Then, we need to sort the quantity property values in ascending order.

So, we are looking for output like:

name quantity color
Apples 4 Red
Apples 6 Yellow
Apples 10 Green
Bananas 5 Yellow
Grapes 2 Green

So, you can see name column is sorted first alphabetically. Then for each having the same name value we sort them by quantity column.

Thus we have

// First
Apples  Bananas  Grapes 
A  B  G

// Then by quantity 
For Apples: 4  6  10
For Bananas: 5
For Grapes: 2

// Final output for quantity column
4  6  10  5  2
Enter fullscreen mode Exit fullscreen mode

Though this logic seems super complex, but its solution is super easy:

let inventory = [
  {name:"Bananas", color:"Yellow", quantity:5},
  {name:"Apples", color:"Red", quantity:4},
  {name:"Apples", color:"Green", quantity:10},
  {name:"Grapes", color:"Green", quantity:2},
  {name:"Apples", color:"Yellow", quantity:6}
];

// Sort by the "name" property value, then by "quantity"
inventory.sort((a, b) => {
  let compareNames = a.name.localeCompare(b.name);
  let compareQuantity = a.quantity - b.quantity;

  // First compare using names
  // If values for "name" porperty for both a & b is same,
  // then compare by "quantity" property value
  return compareNames || compareQuantity;
})

// Output is the same as shown in the above table
Enter fullscreen mode Exit fullscreen mode

Or, we can also write this in a one-line like:

inventory.sort((a, b) => a.name.localeCompare(b.name) || a.quantity - b.quantity);
Enter fullscreen mode Exit fullscreen mode

and we still get the same output.

Descending:

Let say our requirement is now something like:

  1. First, we need to sort the name property values in ascending order.
  2. Then, we need to sort the quantity property values in descending order.

For this we just need to interchange a & b in the sort compare function for just quantity property only like:

// Sort by the "name" property value, then by "quantity" descending order
inventory.sort((a, b) => {
  let compareNames = a.name.localeCompare(b.name);
  let compareQuantity = b.quantity - a.quantity;  // 👈 interchange `a` & `b` here

  // First compare using names
  // If values for "name" porperty for both a & b is same,
  // then compare by "quantity" property value
  return compareNames || compareQuantity;
})
Enter fullscreen mode Exit fullscreen mode

Or, just in one-line like:

inventory.sort((a, b) => a.name.localeCompare(b.name) || b.quantity - a.quantity);
Enter fullscreen mode Exit fullscreen mode

And we get output like:

name quantity color
Apples 10 Green
Apples 6 Yellow
Apples 4 Red
Bananas 5 Yellow
Grapes 2 Green

Back to top


Wrap Up

I hope you will find this post useful and learn something new in the process. If you have any comments, additions or questions please let me know in the comment section.

Feedback, suggestions, and recommendations are highly welcome. This will really help me a lot and motivate me to share more content like this in future also. 😀

Happy Coding!

Discussion (1)

Collapse
lukeshiru profile image
LUKESHIRU

Great post! Thanks for sharing!