Skip to content

Instantly share code, notes, and snippets.

@Ch4ni
Last active September 10, 2025 22:35
Show Gist options
  • Select an option

  • Save Ch4ni/fd4c2f5ef70f75121c14041b46a62282 to your computer and use it in GitHub Desktop.

Select an option

Save Ch4ni/fd4c2f5ef70f75121c14041b46a62282 to your computer and use it in GitHub Desktop.
a slightly generic sorting utilities class

A Generic Utils class for Composite LexoRank sorting

LexoRank

LexoRank is a Ranking/Ordering algorithm or method designed for lists of objects that may or may not frequently change.

For more details on LexoRank, see this article

About EntitySortUtils

I wrote this class as an exercise for composing a multi-tier ordering problem with the primary ordering provided by LexoRank (using a typescript library), and secondary ordering attributes of either date or id.

ToDo

... complete the documentation.

export interface SortableWithId {id: string};
export interface DateSortable extends SortableWithId { date: Date };
export interface LexoRankSortable extends SortableWithId { lexoRank: string };
export type SortFunction = (a: any, b: any) => number;
export class EntitySortUtils {
private static readonly defaultSubSort = (_a: any, _b: any) => 0;
public static composableGenericSortFunctionComposer(
greaterThanPredicate: (e1: any, e2: any) => boolean,
lessThanPredicate: (e1: any, e2: any) => boolean,
subSortFn?: SortFunction
): (e1: any, e2: any) => number {
return (e1: any, e2: any) => {
if(greaterThanPredicate(e1, e2)) return 1;
if(lessThanPredicate(e1, e2)) return -1;
return (subSortFn) ? subSortFn(e1, e2) : 0;
}
}
// composable functions
/**
* Compare two LexoRankSortable entities and return a number. If the dates are equal then sub sort using the subSortFn. This is used for sorting arrays of LexoRankSortable entities.
*
* Results mean:
* > 0: e1 has a higher order than e2
* < 0: e1 has a lower order than e2
* 0: e1 and e2 have equal order
*
* Example Usage:
* let subSortFn = (e1: {someSubField: number}, e2: {someSubField: number}) => e1.someSubField - e2.someSubField
* let sortedArray = lexoRankEntityArray.sort(EntitySortUtils.composableCompareByLexoRank(subSortFn))
*
* @param e1 a LexoRankSortable to compare
* @param e2 a LexoRankSortable to compare
* @param subSortFn a SortFunction to apply when e1.lexoRank == e2.lexoRank
* @returns a number to indicate sort order.
*/
public static composableCompareByLexoRank = (e1: LexoRankSortable, e2: LexoRankSortable, subSortFn?) => this.composableGenericSortFunctionComposer((e1, e2) => e1.lexoRank < e2.lexoRank,(e1, e2) => e1.lexoRank > e2.lexoRank, subSortFn)(e1, e2);
/**
* Compare two DateSortable entities and return a number. If the dates are equal then sub sort using the subSortFn. This is used for sorting arrays of DateSortable entities.
*
* Results mean:
* > 0: e1 has a higher order than e2
* < 0: e1 has a lower order than e2
* 0: e1 and e2 have equal order
*
* Example Usage:
* let subSortFn = (e1: {someSubField: number}, e2: {someSubField: number}) => e1.someSubField - e2.someSubField
* let sortedArray = dateEntityArray.sort(EntitySortUtils.composableCompareByDate(subSortFn))
*
* @param e1 a DateSortable to compare
* @param e2 a DateSortable to compare
* @param subSortFn a SortFunction to apply when e1.date == e2.date
* @returns a number to indicate sort order.
*/
public static composableCompareByDate = (e1: DateSortable, e2: DateSortable, subSortFn) => this.composableGenericSortFunctionComposer((e1, e2) => e1.date < e2.date, (e1, e2) => e1.date > e2.date, subSortFn)(e1, e2);
// Sort functions with a default/static subSort
/**
* Compare two DateSortable entities and return a number. This is used for sorting arrays of DateSortable entities.
*
* Results mean:
* > 0: e1 has a higher order than e2
* < 0: e1 has a lower order than e2
* 0: e1 and e2 have equal order
*
* Example Usage:
* let subSortFn = (e1: {someSubField: number}, e2: {someSubField: number}) => e1.someSubField - e2.someSubField
* let sortedArray = dateEntityArray.sort(EntitySortUtils.composableCompareByDate(subSortFn))
*
* @param e1 a DateSortable to compare
* @param e2 a DateSortable to compare
* @returns a number to indicate sort order.
*/
public static compareByDate = (entity1: DateSortable, entity2: DateSortable) => this.composableCompareByDate(entity1, entity2);
/**
* Compare two LexoRankSortable entities and return a number. This is used for sorting arrays of LexoRankSortable entities.
*
* Results mean:
* > 0: e1 has a higher order than e2
* < 0: e1 has a lower order than e2
* 0: e1 and e2 have equal order
*
* Example Usage:
* let subSortFn = (e1: {someSubField: number}, e2: {someSubField: number}) => e1.someSubField - e2.someSubField
* let sortedArray = lexoRankEntityArray.sort(EntitySortUtils.composableCompareByLexoRank(subSortFn))
*
* @param e1 a LexoRankSortable to compare
* @param e2 a LexoRankSortable to compare
* @returns a number to indicate sort order.
*/
public static compareByLexoRank = (entity1: LexoRankSortable, entity2: LexoRankSortable) => this.composableCompareByLexoRank(entity1, entity2)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment