UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

158 lines (157 loc) 5.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sortNormal = sortNormal; exports.sortObjectArrayByKey = sortObjectArrayByKey; exports.sortTwoDimensionalArray = sortTwoDimensionalArray; exports.stableSort = stableSort; const types_1 = require("./types"); function sortNormal(a, b) { if (!(0, types_1.isNumber)(a) && !(0, types_1.isString)(a)) { error(`Failed to normal sort since the first value was not a number or string and was instead: ${type(a)}`); } if (!(0, types_1.isNumber)(b) && !(0, types_1.isString)(b)) { error(`Failed to normal sort since the second value was not a number or string and was instead: ${type(b)}`); } if (a < b) { return -1; } if (a > b) { return 1; } return 0; } /** * Helper function to sort an array of objects by one of the object keys. * * For example: * * ```ts * const myArray = [ * { * name: "alice", * age: 30, * }, * { * name: "bob", * age: 20, * }, * ]; * myArray.sort(sortObjectArrayByKey("age")); * ``` */ function sortObjectArrayByKey(key) { return (a, b) => { if (!(0, types_1.isTable)(a)) { error(`Failed to sort an object array by the key of "${key}" since the first element was not a table and was instead: ${type(a)}`); } if (!(0, types_1.isTable)(b)) { error(`Failed to sort an object array by the key of "${key}" since the second element was not a table and was instead: ${type(b)}.`); } const aValue = a.get(key); const bValue = b.get(key); return sortNormal(aValue, bValue); }; } /** * Helper function to sort a two-dimensional array by the first element. * * For example: * * ```ts * const myArray = [[1, 2], [2, 3], [3, 4]]; * myArray.sort(sortTwoDimensionalArray); * ``` * * This function also properly handles when the array elements are strings or numbers (instead of * another array). * * From: * https://stackoverflow.com/questions/16096872/how-to-sort-2-dimensional-array-by-column-value */ function sortTwoDimensionalArray(a, b) { const aType = type(a); const bType = type(b); if (aType !== bType) { error(`Failed to two-dimensional sort since the two elements were disparate types: ${a} & ${b} (${aType} & ${bType})`); } if (aType === "string" || aType === "number") { return sortNormal(a, b); } if (aType !== "table") { error("Failed to two-dimensional sort since the first element was not a string, number, or table."); } if (bType !== "table") { error("Failed to two-dimensional sort since the second element was not a string, number, or table."); } const firstElement1 = a[0]; const firstElement2 = b[0]; if (firstElement1 === undefined || firstElement1 === null) { error("Failed to two-dimensional sort since the first element of the first array was undefined."); } if (firstElement2 === undefined || firstElement2 === null) { error("Failed to two-dimensional sort since the first element of the second array was undefined."); } const elementType1 = type(firstElement1); const elementType2 = type(firstElement2); if (elementType1 !== elementType2) { error(`Failed to two-dimensional sort since the first element of each array were disparate types: ${firstElement1} & ${firstElement2} (${elementType1} & ${elementType2})`); } return sortNormal(firstElement1, firstElement2); } /** * Helper function to sort an array in a stable way. * * This is useful because by default, the transpiled `Array.sort` method from TSTL is not stable. * * Under the hood, this uses the merge sort algorithm. */ function stableSort( // eslint-disable-next-line complete/prefer-readonly-parameter-types array, sortFunc = sortNormal) { // Base case: an array of zero or one elements is already sorted if (array.length <= 1) { return array; } // Split the array into two halves. const middleIndex = Math.floor(array.length / 2); const leftArray = array.slice(0, middleIndex); const rightArray = array.slice(middleIndex); // Recursively sort each half. const sortedLeftArray = stableSort(leftArray, sortFunc); const sortedRightArray = stableSort(rightArray, sortFunc); // Merge the two sorted halves. const mergedArray = []; let leftIndex = 0; let rightIndex = 0; while (leftIndex < sortedLeftArray.length && rightIndex < sortedRightArray.length) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const left = sortedLeftArray[leftIndex]; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const right = sortedRightArray[rightIndex]; const sortResult = sortFunc(left, right); if (sortResult === -1 || sortResult === 0) { mergedArray.push(left); leftIndex++; } else { mergedArray.push(right); rightIndex++; } } // Add any remaining elements from the left array. while (leftIndex < sortedLeftArray.length) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const left = sortedLeftArray[leftIndex]; mergedArray.push(left); leftIndex++; } // Add any remaining elements from the right array. while (rightIndex < sortedRightArray.length) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const right = sortedRightArray[rightIndex]; mergedArray.push(right); rightIndex++; } return mergedArray; }