JS: Array.prototype.sort

By Xah Lee. Date: . Last updated: .
xArray.sort()
  • Sort elements by convert each element to string and compare their Code Unit order. (this means, if the array elements are all strings, and they are ASCII Characters, then it's sorted by alphabetical order.)
  • Sort is done in-place (original array modified), return the reference to the array.

since ECMAScript 2019, sort does stable sort.

🛑 WARNING: Always add a sort function as argument. The default sort behavior is basically useless.

// array default sort, items are treated as string
// 40 comes before 9
console.assert(JSON.stringify([9, 40, 2].sort()) === `[2,40,9]`);
xArray.sort(f)

Sort xArray in-place, return reference to the array.

  • f is a ordering function.
  • f is given 2 arguments x y, and it should return:
  • negative number if x ≺ y
  • 0 if x = y
  • positive number if x ≻ y.
// sort array as numbers

const aa = [9, 40, 2];

aa.sort((x, y) => {
 if (x < y) return -1;
 if (x > y) return 1;
 if (x == y) return 0;
});

// elegant but less efficient
// aa.sort((aa, bb) => (aa - bb));

console.assert(JSON.stringify(aa) === "[2,9,40]");

Example: Custom Order Function

Sorting array using custom order function.

// array sort using custom function

/*
we want to sort these string by the embeded numbers
["a1", "a70", "a8", "A2"]
*/

console.log(
 ["a1", "a70", "a8", "A2"].sort((x, y) => {
  // x and y are strings. we remove first char. consider rest as number
  const nx = parseInt(x.slice(1));
  const ny = parseInt(y.slice(1));
  if (nx < ny) return -1;
  if (nx > ny) return 1;
  if (nx == ny) return 0;
 }),
);
// [ "a1", "A2", "a8", "a70" ]

Example: Default Order Function

Here is example showing it sorts by code unit and not codepoint.

/*
example showing default comparison function for string, sorts by code unit and not codepoint.
*/

console.log(["fi", "🦋"].sort());
// [ "🦋", "fi" ]

/*
the ligature fi has codepoint 64257
the butterfly 🦋 has codepoint 129419
if order by codepoint, fi should come first.

fi
name: LATIN SMALL LIGATURE FI
Codepoint 64257
HEXD FB01
UTF16 encoding: FB01

🦋
name: BUTTERFLY
Codepoint 129419
HEXD 1F98B
UTF16 encoding: D83E DD8B
*/

Order Function Must be Consistent

🛑 WARNING: The custom order function must be consistent, else the result of sort is unpredictable.

Consistent means, for any x y z in the array:

  1. f(x,x) === 0
  2. if f(x,y) === 0 and f(y,z) === 0 then f(x,z) === 0
  3. if f(x,y) === -1 and f(y,z) === -1 then f(x,z) === -1
  4. if f(x,y) === 1 and f(y,z) === 1 then f(x,z) === 1

The above guarantee that the set is partitioned into classes by a equivalence relation, and the equivalence classes are total ordered.

also, the following are required due to how JavaScript the language works:

Edge cases

Sparse Array

empty items are filled by values of undefined and moved to the end.

// sparse array
const xx = [8, 9, , , 3];
console.log(xx);
// [ 8, 9, <2 empty items>, 3 ]

// sort array as numbers
xx.sort((x, y) => {
  if (x < y) return -1;
  if (x > y) return 1;
  if (x == y) return 0;
});

console.log(xx);
// [ 3, 8, 9, <2 empty items> ]

Array-Like Object

works on Array-Like Object. Return a Array-Like Object.

// array-like object
let xx = { 0: "b", 1: "a", length: 4 };

// sort a array-like object
Reflect.apply(Array.prototype.sort, xx, []);

// return array-like object
console.log(xx);
// { "0": "a", "1": "b", length: 2 }

JavaScript. Sort, Reverse