This site runs best with JavaScript enabled.

JavaScript Array Sort - In Depth (and some handy sort utilities)

September 27, 2020


This post describes JavaScript's array sort method with examples of arrays of values, arrays of objects and sorting an object by key. s

Simple Examples

Array.prototype.sort() sorts an array in place (i.e., it mutates the original array).

Todo - default sort description

To sort numbers:

1const numbers = [4, 8, 2, 0]
2numbers.sort()
3console.log(numbers) // -> [0, 2, 4, 8]

To sort strings:

1const strings = ['c', 'd', 'b', 'a']
2strings.sort()
3console.log(strings) // -> ["a", "b", "c", "d"]

Todo - for custom sorts, objects or unique sort ordering. Visualisation diagram - number line: <- -1 0 +1 -> function mySort(firstItem, secondItem)

To sort objects you need to use a custom sort function.

The equivalent sort function for the 2 examples above is:

1function defaultSort(a, b) {
2 if (a < b) {
3 return -1 // A negative result moves `a` before `b` to a lower
4 // array index.
5 }
6
7 if (b < a) {
8 return 1 // A positive result moves `a` after `b` to a higher
9 // array index.
10 }
11
12 return 0 // A zero result leaves 'a' and 'b' in the same order,
13 // relative to each other
14 // (other array items might get sorted above them)
15}

To use this sort function:

1const numbers = [4, 8, 2, 0]
2numbers.sort(defaultSort)
3console.log(numbers) // -> [0, 2, 4, 8]

With es6 you can simplify this sort function:

1const numbers = [4, 8, 2, 0]
2numbers.sort((a, b) => a - b)
3console.log(numbers) // -> [0, 2, 4, 8]

Sorting an Array of Objects by Property

Here is the array of objects we will be working with:

1const employees = [
2 {
3 name: 'Jane',
4 salary: 20000,
5 role: 'Programmer'
6 },
7 {
8 name: 'Dave',
9 salary: 25000,
10 role: 'Programmer'
11 },
12 {
13 name: 'Ben',
14 salary: 10000,
15 role: 'Programmer'
16 },
17 {
18 name: 'Carol',
19 salary: 50000,
20 role: 'Manager'
21 },
22 {
23 name: 'Bob',
24 salary: 25000,
25 role: 'Programmer'
26 },
27 {
28 name: 'Alice',
29 salary: 15000,
30 role: 'Programmer'
31 },
32 {
33 name: 'Carol',
34 salary: 100000,
35 role: 'CEO'
36 },
37 {
38 name: 'Dave',
39 salary: 20000,
40 role: 'Programmer'
41 }
42]

You sort objects by property:

1function sortByName({name: a}, {name: b}) {
2 if (a < b) {
3 return -1
4 }
5
6 if (b < a) {
7 return 1
8 }
9
10 return 0
11}
12
13employees.sort(sortByName)

You can generalise this to work for any properties:

1const sortByProp = (prop) => (a, b) => {
2 if (a[prop] < b[prop]) {
3 return -1
4 }
5
6 if (b[prop] < a[prop]) {
7 return 1
8 }
9
10 return 0
11}

It can be used like this:

1const sortByName = sortByProp('name')
2
3employees.sort(sortByName)

Sorting Objects by Multiple Properties

The trick is to apply subsequent sort criteria only when earlier sort criteria return '0', i.e., the previous sort criteria considered the items to be equal.

This can be done with a single sort function, but I find it much easier to use an order function to compose the sort functions:

1const order = (...fns) => (...args) => {
2 let res = 0, i = 0;
3 while (
4 fns[i] !== undefined &&
5 (res = fns[i++](...args)) === 0
6 );
7
8 return res
9}
10
11const byName = sortByProp('name')
12const bySalary = sortByProp('salary')
13const byRole = sortByProp('role')
14
15employees.sort(
16 order(
17 byName,
18 bySalary,
19 byRole,
20 )
21)
22
23console.log(employees)

This code reads much easier and, if you wanted to change the order of the sort criteria, you simply swap the order of the functions:

1employees.sort(
2 order(
3 byRole,
4 bySalary,
5 byName,
6 )
7)

An added benefit is it makes it much easier to write individual unit tests for each tiny sort function!

Sorting Objects by Key

Finally, to sort an object by keys you use the Object.entries and Object.fromEntries methods.

1const fruits = {
2 'oranges': {
3 cost: .8,
4 quantity: 3
5 },
6 'bananas': {
7 cost: .75,
8 quantity: 5
9 },
10 'apples': {
11 cost: .5,
12 quantity: 10
13 }
14}
15
16const sorted = Object.fromEntries(
17 Object.entries(
18 fruits
19 ).sort(([key]) => key)
20)
21
22console.log(sorted)

How does this work?

  1. Object.entries(fruits) returns an array of arrays. Each sub array contains two elements: key and object:
1[
2 ["oranges", {
3 cost: 0.8,
4 quantity: 3
5 }], ["bananas", {
6 cost: 0.75,
7 quantity: 5
8 }], ["apples", {
9 cost: 0.5,
10 quantity: 10
11 }]
12]
  1. .sort(([key]) => key) uses an es6 arrow function and destructuring to sort each array by the first element: key

  2. Object.fromEntries converts the "array of arrays" back to an object.

Share article



neohed © 2022