JavaScript Array Sort - In Depth (and some handy sort utilities)
Dave
Posted on October 2, 2020
This post describes JavaScript's array sort method with examples of arrays of values, arrays of objects and sorting an object by key.
Simple Examples
Array.prototype.sort()
sorts an array in place (i.e., it mutates the original array).
To sort numbers:
const numbers = [4, 8, 2, 0]
numbers.sort()
console.log(numbers) // -> [0, 2, 4, 8]
To sort strings:
const strings = ['c', 'd', 'b', 'a']
strings.sort()
console.log(strings) // -> ["a", "b", "c", "d"]
To sort objects you need to use a custom sort function.
The equivalent sort function for the 2 examples above is:
function defaultSort(a, b) {
if (a < b) {
return -1 // A negative result moves `a` before `b` to a lower
// array index.
}
if (b < a) {
return 1 // A positive result moves `a` after `b` to a higher
// array index.
}
return 0 // A zero result leaves 'a' and 'b' in the same order,
// relative to each other
// (other array items might get sorted above them)
}
To use this sort function:
const numbers = [4, 8, 2, 0]
numbers.sort(defaultSort)
console.log(numbers) // -> [0, 2, 4, 8]
With es6 you can simplify this sort function:
const numbers = [4, 8, 2, 0]
numbers.sort((a, b) => a - b)
console.log(numbers) // -> [0, 2, 4, 8]
Sorting an Array of Objects by Property
Here is the array of objects we will be working with:
const employees = [
{
name: 'Jane',
salary: 20000,
role: 'Programmer'
},
{
name: 'Dave',
salary: 25000,
role: 'Programmer'
},
{
name: 'Ben',
salary: 10000,
role: 'Programmer'
},
{
name: 'Carol',
salary: 50000,
role: 'Manager'
},
{
name: 'Bob',
salary: 25000,
role: 'Programmer'
},
{
name: 'Alice',
salary: 15000,
role: 'Programmer'
},
{
name: 'Carol',
salary: 100000,
role: 'CEO'
},
{
name: 'Dave',
salary: 20000,
role: 'Programmer'
}
]
You sort objects by property:
function sortByName({name: a}, {name: b}) {
if (a < b) {
return -1
}
if (b < a) {
return 1
}
return 0
}
employees.sort(sortByName)
You can generalise this to work for any properties:
const sortByProp = (prop) => (a, b) => {
if (a[prop] < b[prop]) {
return -1
}
if (b[prop] < a[prop]) {
return 1
}
return 0
}
It can be used like this:
const sortByName = sortByProp('name')
employees.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:
const order = (...fns) => (...args) => {
let res = 0, i = 0;
while (
fns[i] !== undefined &&
(res = fns[i++](...args)) === 0
);
return res
}
const byName = sortByProp('name')
const bySalary = sortByProp('salary')
const byRole = sortByProp('role')
employees.sort(
order(
byName,
bySalary,
byRole,
)
)
console.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:
employees.sort(
order(
byRole,
bySalary,
byName,
)
)
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.
const fruits = {
'oranges': {
cost: .8,
quantity: 3
},
'bananas': {
cost: .75,
quantity: 5
},
'apples': {
cost: .5,
quantity: 10
}
}
const sorted = Object.fromEntries(
Object.entries(
fruits
).sort(([key]) => key)
)
console.log(sorted)
How does this work?
-
Object.entries(fruits)
returns an array of arrays. Each sub array contains two elements:key
andobject
:
[
["oranges", {
cost: 0.8,
quantity: 3
}], ["bananas", {
cost: 0.75,
quantity: 5
}], ["apples", {
cost: 0.5,
quantity: 10
}]
]
.sort(([key]) => key)
uses an es6 arrow function and destructuring to sort each array by the first element:key
Object.fromEntries
converts the "array of arrays" back to an object.
Posted on October 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.