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

neohed

Dave

Posted on October 2, 2020

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

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]
Enter fullscreen mode Exit fullscreen mode

To sort strings:

const strings = ['c', 'd', 'b', 'a']
strings.sort()
console.log(strings) // -> ["a", "b", "c", "d"]
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

To use this sort function:

const numbers = [4, 8, 2, 0]
numbers.sort(defaultSort)
console.log(numbers) // -> [0, 2, 4, 8]
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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'
    }
]
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

It can be used like this:

const sortByName = sortByProp('name')

employees.sort(sortByName)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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,
  )
)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

How does this work?

  1. Object.entries(fruits) returns an array of arrays. Each sub array contains two elements: key and object:
[
  ["oranges", {
    cost: 0.8,
    quantity: 3
  }], ["bananas", {
    cost: 0.75,
    quantity: 5
  }], ["apples", {
    cost: 0.5,
    quantity: 10
  }]
]
Enter fullscreen mode Exit fullscreen mode
  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.

💖 💪 🙅 🚩
neohed
Dave

Posted on October 2, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related