JS: Array.prototype.sort
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:
f(x,x) === 0- if
f(x,y) === 0andf(y,z) === 0thenf(x,z) === 0 - if
f(x,y) === -1andf(y,z) === -1thenf(x,z) === -1 - if
f(x,y) === 1andf(y,z) === 1thenf(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:
typeof f(x,y) === "number"and is notNaNf(x,y)always returns the same value.- Calling
f(x,y)does not modify the array or any object of array's Prototype Chain.
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 }