Skip to content

Instantly share code, notes, and snippets.

@Phoenix35
Last active May 4, 2019 22:32
Show Gist options
  • Save Phoenix35/e81465c933a8ec8ce95483e6c9fadaf3 to your computer and use it in GitHub Desktop.
Save Phoenix35/e81465c933a8ec8ce95483e6c9fadaf3 to your computer and use it in GitHub Desktop.
A few utility functions to make sorting easier
function shallowCompare (comparator, prop) {
return ({ [prop]: a }, { [prop]: b }) => comparator(a, b);
}
function deepCompare (comparator, props) {
return (aRoot, bRoot) => {
let a = aRoot,
b = bRoot;
for (const prop of props) {
if (!(
Object.prototype.hasOwnProperty.call(a, prop) &&
Object.prototype.hasOwnProperty.call(b, prop)
))
return 0;
a = a[prop];
b = b[prop];
}
return comparator(a, b);
};
}
function buildComp (props) {
return props == null
? this
: typeof props === "string" || typeof props === "symbol"
? shallowCompare(this, props)
: deepCompare(this, props);
}
// MUST NOT be used for locale-aware numerical sorting
// Even with options.numeric = true...
export const buildStrComp =
(props, locales = "en-US", options) =>
buildComp.call(new Intl.Collator(locales, options).compare, props);
// ... Please convert them to numbers or bigints beforehand and use these
export const buildNumAscComp = buildComp.bind((a, b) => a - b);
export const buildNumDesComp = buildComp.bind((a, b) => b - a);
// Simple example on numbers
import { buildNumAscComp } from "path/to/sort.mjs";
const byAsc = buildNumAscComp();
[11, 100, 20].sort(byAsc);
/* [11, 20, 100] */
// Example of shallow on numbers
import { buildNumDesComp } from "path/to/sort.mjs";
const byDescMoney = buildNumDesComp("money");
[{ id: 1, money: 11 }, { id: 2, money: 100 }].sort(byDescMoney);
/* [
0: Object { id: 2, money: 100 }
1: Object { id: 1, money: 11 }
] */
// Example of shallow on strings
import { buildStrComp } from "path/to/sort.mjs";
const bySurname = buildStrComp("surname");
[{ id: 1, name: "Butch", surname: "Cassidy" }, { id: 2, name: "Jack", surname: "Black" }].sort(bySurname);
/* [
0: Object { id: 2, name: "Jack", surname: "Black" }
1: Object { id: 1, name: "Butch", surname: "Cassidy" }
] */
// Example of deep on numbers + array access
import { buildNumAscComp } from "path/to/sort.mjs";
const byElevationAtEnd = buildNumAscComp(["end", 2]);
/*
PointCylinder
[0] r
[1] Θ
[2] z
*/
[
{
start: [10, Math.PI / 4, 8],
end : [10, Math.PI , 11],
},
{
start: [0, 0.1, 0],
end : [1, 2.9, -2],
},
{
start: [2, Math.PI * 2 / 3, 11],
end : [7, 0 , 11],
},
].sort(byElevationAtEnd);
// Stability is not in the spec <https://devdocs.io/javascript/global_objects/array/sort#Description>
// but all engines since 2019 use a stable algorithm anyway (yes, even Edge 18)
/* [
0: Object {
end: Array(3) [ 1, 2.9, -2 ]
start: Array(3) [ 0, 0.1, 0 ]
}
1: Object {
end: Array(3) [ 10, 3.141592653589793, 11 ] // stable
start: Array(3) [ 10, 0.7853981633974483, 8 ]
}
2: Object {
end: Array(3) [ 7, 0, 11 ] // stable
start: Array(3) [ 2, 2.0943951023931953, 11 ]
}
] */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment