Last active
January 11, 2022 22:09
-
-
Save monkpit/b8e04a77c89d12bd1217b0c3bbad55fc to your computer and use it in GitHub Desktop.
Numeric Prop Sorter - given a prop and an optional callback (for when equal values will be sub-sorted), returns a function to be passed to Array.sort
This file contains 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
/** | |
* Creates a sort function that will compare based upon a certain property in an object. | |
* | |
* @param {keyof T} prop - the property of the object to sort by | |
* @param [options.order] the order to sort - either 'asc' or 'desc' | |
* @param [options.callback] callback used as a tiebreaker when the property on both objects is equal. | |
* @returns A function to be passed to Array.sort(); | |
*/ | |
export const numericPropSort = | |
<P extends string, T extends Record<P | keyof T, number>>( | |
prop: P, | |
options?: { | |
order?: "asc" | "desc"; | |
callback?: (a: T, b: T) => number; | |
} | |
) => | |
(a: T, b: T): number => { | |
let { callback, order } = options ?? {}; | |
order = order ?? "asc"; | |
if (a[prop] > b[prop]) return order === "asc" ? 1 : -1; | |
if (a[prop] < b[prop]) return order === "asc" ? -1 : 1; | |
return callback ? callback(a, b) : 0; | |
}; |
This file contains 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
import numericPropSort from './numericPropSort'; | |
import faker from 'faker/locale/en_US'; | |
interface Foo { | |
name: string; | |
data: string; | |
isValid: boolean; | |
index: number; | |
secondaryIndex: number; | |
tertiaryIndex: number; | |
}; | |
const fooFactory = (): Foo => ({ | |
name: faker.commerce.productName(), | |
data: faker.commerce.department(), | |
isValid: faker.datatype.boolean(), | |
index: faker.datatype.number(1), | |
secondaryIndex: faker.datatype.number(99), | |
tertiaryIndex: faker.datatype.number(99) | |
}); | |
// create test arrays | |
const fooArray = new Array(4).fill(null).map(() => fooFactory()); | |
const barArray = new Array(4).fill(null).map((_, i) => ({ index: Math.trunc(i/2), secondaryIndex: 10-i })); | |
const bazArray = new Array(4).fill(null).map((_, i) => ({ index: Math.trunc(i/2) })); | |
// create sorters | |
const subSorter = numericPropSort("secondaryIndex"); | |
const reverseSubSorter = numericPropSort("secondaryIndex", { order: "desc" }); | |
const fooSorter = numericPropSort("index", { callback: subSorter }); | |
const reverseFooSorter = numericPropSort("index", { | |
callback: reverseSubSorter, | |
}); | |
console.log('fooArray - Normal sorting'); | |
console.table(fooArray.sort(fooSorter)); | |
console.log('fooArray - Sort secondaryIndex in reverse'); | |
console.table(fooArray.sort(reverseFooSorter)); | |
console.log('barArray - Normal sorting'); | |
console.table(barArray.sort(fooSorter)); | |
console.log('barArray - Sort secondaryIndex in reverse'); | |
console.table(barArray.sort(reverseFooSorter)); | |
console.table(bazArray); | |
console.table(bazArray.sort(fooSorter)); | |
// ^ this line has a compiler error since bazArray's elements | |
// do not contain both `index` and `secondaryIndex` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment