UNPKG

houser-js-utils

Version:

A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.

325 lines (324 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const ArrayUtils = { /** * Calculates the average of all numbers in an array * @param arr - Array of numbers to calculate average from * @returns The average of all numbers, or 0 if array is empty * @example * ```typescript * const avg = ArrayUtils.average([1, 2, 3, 4, 5]); // Returns 3 * ``` */ average(arr) { if (!Array.isArray(arr) || arr.length === 0) return 0; return this.sumArray(arr) / arr.length; }, /** * Compares two arrays for equality by sorting and comparing elements * @param a1 - First array to compare * @param a2 - Second array to compare * @returns True if arrays contain the same elements in any order * @example * ```typescript * const equal = ArrayUtils.arrayEquals([1, 2, 3], [3, 2, 1]); // Returns true * ``` */ arrayEquals(a1, a2) { if (!Array.isArray(a1) || !Array.isArray(a2)) return false; if (a1.length !== a2.length) return false; const sortedA1 = [...a1].sort(this.sortCompare); const sortedA2 = [...a2].sort(this.sortCompare); return sortedA1.every((v, i) => v === sortedA2[i]); }, /** * Splits an array into chunks of specified size * @param arr - Array to split into chunks * @param size - Size of each chunk (must be positive) * @returns Array of arrays, each of size 'size' * @throws Error if size is not positive */ chunks(arr, size) { if (!Number.isInteger(size) || size <= 0) { throw new Error("Chunk size must be a positive integer"); } const chunks = []; for (let i = 0; i < arr.length; i += size) { chunks.push(arr.slice(i, i + size)); } return chunks; }, /** * Compares two arrays for equality based on the given options * @param arr1 - First array to compare * @param arr2 - Second array to compare * @param options - Comparison options * @returns True if arrays are equal based on the options */ compareArrays(arr1, arr2, options = {}) { if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false; const { ordered = false, deep = false } = options; if (arr1.length !== arr2.length) return false; if (ordered) { return arr1.every( (item, index) => deep ? this.deepEqual(item, arr2[index]) : item === arr2[index] ); } else { const visited = new Array(arr2.length).fill(false); return arr1.every((item1) => { const index = arr2.findIndex( (item2, i) => !visited[i] && (deep ? this.deepEqual(item1, item2) : item1 === item2) ); if (index === -1) return false; visited[index] = true; return true; }); } }, /** * Returns a new array with unique values * @param array - Array to make unique * @returns Array with duplicate values removed */ deduplicate(array) { if (!Array.isArray(array)) return []; return Array.from(new Set(array)); }, /** * Deep equality comparison between two values * @param a - First value * @param b - Second value * @returns True if values are deeply equal */ deepEqual(a, b) { if (a === b) return true; if (typeof a !== typeof b) return false; if (typeof a === "object" && a !== null && b !== null) { if (Array.isArray(a) !== Array.isArray(b)) return false; if (Array.isArray(a)) { if (a.length !== b.length) return false; return a.every((val, i) => this.deepEqual(val, b[i])); } const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; return keysA.every( (key) => this.deepEqual( a[key], b[key] ) ); } return false; }, /** * Returns elements from array a that are not in array b based on id property * @param a - First array * @param b - Second array * @param getId - Optional function to extract id from items * @returns Array of elements from a that are not in b */ difference(a, b, getId = (item) => item.id) { const bIds = new Set(b.map(getId)); return a.filter((item) => !bIds.has(getId(item))); }, /** * Returns the maximum value in an array * @param arr - Array of comparable values * @returns Maximum value or undefined if array is empty */ findMax(arr) { if (!Array.isArray(arr) || arr.length === 0) return void 0; return arr.reduce((max, val) => val > max ? val : max, arr[0]); }, /** * Returns the minimum value in an array * @param arr - Array of comparable values * @returns Minimum value or undefined if array is empty */ findMin(arr) { if (!Array.isArray(arr) || arr.length === 0) return void 0; return arr.reduce((min, val) => val < min ? val : min, arr[0]); }, /** * Finds and updates an item in a collection based on id * @param collection - Collection to update * @param item - Item to update * @returns Updated collection * @throws Error if item is not found */ findAndUpdate(collection, item) { const index = collection.findIndex((b) => b.id === item.id); if (index === -1) { throw new Error(`Item with id ${item.id} not found in collection`); } return collection.map((element, i) => i === index ? item : element); }, /** * Flattens a nested array to a specified depth * @param arr - Array to flatten * @param depth - Maximum depth to flatten (default: Infinity) * @returns Flattened array */ flatten(arr, depth = Infinity) { if (depth <= 0) return arr.slice(); if (!Array.isArray(arr)) return [arr]; return arr.reduce((acc, val) => { if (Array.isArray(val)) { acc.push(...this.flatten(val, depth - 1)); } else { acc.push(val); } return acc; }, []); }, /** * Groups array elements by a key or function * @param arr - Array to group * @param keyOrFn - Key to group by or function that returns the group key * @returns Object with grouped arrays */ groupBy(arr, keyOrFn) { if (!Array.isArray(arr)) return {}; return arr.reduce((groups, item) => { const key = typeof keyOrFn === "function" ? keyOrFn(item) : String(item[keyOrFn]); groups[key] = groups[key] || []; groups[key].push(item); return groups; }, {}); }, /** * Checks if two arrays have any common elements * @param array1 - First array * @param array2 - Second array * @returns True if arrays share at least one common element */ hasCommonElement(array1, array2) { if (!array1?.length || !array2?.length) return false; const [smaller, larger] = array1.length < array2.length ? [array1, array2] : [array2, array1]; const set = new Set(smaller); return larger.some((element) => set.has(element)); }, /** * Returns the intersection of two arrays * @param arr1 - First array * @param arr2 - Second array * @returns Array containing elements present in both arrays */ intersection(arr1, arr2) { if (!Array.isArray(arr1) || !Array.isArray(arr2)) return []; const set = new Set(arr2); return arr1.filter((item) => set.has(item)); }, /** * Moves an item from one position to another in an array * @param arr - Array to modify * @param from - Source index * @param to - Destination index * @returns New array with item moved * @throws Error if indices are out of bounds */ moveItem(arr, from, to) { if (!Array.isArray(arr)) { throw new Error("First argument must be an array"); } if (from < 0 || from >= arr.length) { throw new Error(`Source index ${from} is out of bounds`); } if (to < 0 || to >= arr.length) { throw new Error(`Destination index ${to} is out of bounds`); } const newArr = [...arr]; const [item] = newArr.splice(from, 1); newArr.splice(to, 0, item); return newArr; }, /** * Returns a random element from the array * @param arr - Array to get element from * @returns Random element or undefined if array is empty */ random(arr) { if (!Array.isArray(arr) || arr.length === 0) return void 0; return arr[Math.floor(Math.random() * arr.length)]; }, /** * Removes elements from an array that match a predicate * @param arr - Array to remove elements from * @param predicate - Function that returns true for elements to remove * @returns New array with matching elements removed */ remove(arr, predicate) { if (!Array.isArray(arr)) return []; return arr.filter((item) => !predicate(item)); }, /** * Returns a new array with elements in random order * @param arr - Array to shuffle * @returns New array with elements in random order */ shuffle(arr) { if (!Array.isArray(arr)) return []; const result = [...arr]; for (let i = result.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [result[i], result[j]] = [result[j], result[i]]; } return result; }, /** * Compares two values for sorting * @param x - First value to compare * @param y - Second value to compare * @returns -1 if x < y, 0 if equal, 1 if x > y */ sortCompare(x, y) { const pre = ["string", "number", "bool"]; if (typeof x !== typeof y) { return pre.indexOf(typeof y) - pre.indexOf(typeof x); } if (x === y) { return 0; } return x > y ? 1 : -1; }, /** * Returns the sum of all numbers in an array * @param arr - Array of numbers * @returns Sum of all numbers */ sumArray(arr) { if (!Array.isArray(arr)) return 0; return arr.reduce((sum, num) => sum + (Number(num) || 0), 0); }, /** * Returns the first n elements of an array * @param arr - Array to get elements from * @param n - Number of elements to get (default: 1) * @returns Array containing the first n elements */ takeFirst(arr, n = 1) { if (!Array.isArray(arr)) return []; return arr.slice(0, n); }, /** * Returns the last n elements of an array * @param arr - Array to get elements from * @param n - Number of elements to get (default: 1) * @returns Array containing the last n elements */ takeLast(arr, n = 1) { if (!Array.isArray(arr)) return []; return arr.slice(-n); }, /** * Returns the union of multiple arrays * @param arrays - Arrays to union * @returns Array containing unique elements from all arrays */ union(...arrays) { return this.deduplicate(arrays.flat()); } }; exports.ArrayUtils = ArrayUtils; //# sourceMappingURL=ArrayUtils.js.map