UNPKG

nhb-toolbox

Version:

A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.

106 lines (105 loc) 4.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.naturalSort = naturalSort; exports.sortAnArray = sortAnArray; const non_primitives_1 = require("../guards/non-primitives"); const primitives_1 = require("../guards/primitives"); function naturalSort(a, b, options) { const { caseInsensitive = true, localeAware = false } = options || {}; const _createChunks = (str) => { const chunks = []; let current = ''; let isNumeric = false; for (const char of str) { const charIsNum = !Number.isNaN(Number(char)); if (current?.length === 0) { current = char; isNumeric = charIsNum; continue; } if (charIsNum === isNumeric) { current += char; } else { chunks?.push(isNumeric ? Number(current) : current); current = char; isNumeric = charIsNum; } } if (current?.length > 0) { chunks?.push(isNumeric ? Number(current) : current); } return chunks; }; const aChunks = _createChunks(a); const bChunks = _createChunks(b); for (let i = 0; i < Math.min(aChunks?.length, bChunks?.length); i++) { let aChunk = aChunks[i]; let bChunk = bChunks[i]; if (caseInsensitive && (0, primitives_1.isString)(aChunk) && (0, primitives_1.isString)(bChunk)) { aChunk = aChunk?.toLowerCase(); bChunk = bChunk?.toLowerCase(); } if (typeof aChunk !== typeof bChunk) { return (0, primitives_1.isString)(aChunk) ? 1 : -1; } if (aChunk !== bChunk) { if ((0, primitives_1.isNumber)(aChunk) && (0, primitives_1.isNumber)(bChunk)) { return aChunk - bChunk; } if ((0, primitives_1.isString)(aChunk) && (0, primitives_1.isString)(bChunk)) { if (localeAware) { const cmp = aChunk.localeCompare(bChunk, undefined, { sensitivity: caseInsensitive ? 'accent' : 'variant', }); if (cmp !== 0) return cmp; } return aChunk < bChunk ? -1 : 1; } } } return aChunks?.length - bChunks?.length; } function sortAnArray(array, options) { if (!(0, non_primitives_1.isValidArray)(array)) return array; if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isString)) { return [...array].sort((a, b) => options?.sortOrder === 'desc' ? naturalSort(b, a) : naturalSort(a, b)); } if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isNumber)) { return [...array].sort((a, b) => (options?.sortOrder === 'desc' ? b - a : a - b)); } if ((0, non_primitives_1.isArrayOfType)(array, primitives_1.isBoolean)) { return [...array].sort((a, b) => options?.sortOrder === 'desc' ? Number(b) - Number(a) : Number(a) - Number(b)); } if ((0, non_primitives_1.isArrayOfType)(array, non_primitives_1.isObject) && options && 'sortByField' in options) { return [...array].sort((a, b) => { const _getKeyValue = (obj, path) => { return path .split('.') .reduce((acc, key) => acc?.[key], obj); }; const keyA = _getKeyValue(a, options?.sortByField); const keyB = _getKeyValue(b, options?.sortByField); if (keyA == null || keyB == null) { return keyA == null ? 1 : -1; } if ((0, primitives_1.isString)(keyA) && (0, primitives_1.isString)(keyB)) { return options?.sortOrder === 'desc' ? naturalSort(keyB, keyA) : naturalSort(keyA, keyB); } if ((0, primitives_1.isNumber)(keyA) && (0, primitives_1.isNumber)(keyB)) { return options?.sortOrder === 'desc' ? keyB - keyA : keyA - keyB; } if ((0, primitives_1.isBoolean)(keyA) && (0, primitives_1.isBoolean)(keyB)) { return options?.sortOrder === 'desc' ? Number(keyB) - Number(keyA) : Number(keyA) - Number(keyB); } return 0; }); } return [...array]; }