Last active
May 4, 2019 22:32
-
-
Save Phoenix35/e81465c933a8ec8ce95483e6c9fadaf3 to your computer and use it in GitHub Desktop.
A few utility functions to make sorting easier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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