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.

1 lines 19.1 kB
{"version":3,"file":"ArrayUtils.mjs","sources":["../src/ArrayUtils.ts"],"sourcesContent":["/**\n * @module ArrayUtils\n * @description A collection of utility functions for array manipulation and operations.\n * @example\n * ```typescript\n * import { ArrayUtils } from 'houser-js-utils';\n *\n * // Get unique values from an array\n * const unique = ArrayUtils.deduplicate([1, 2, 2, 3]);\n *\n * // Find maximum value\n * const max = ArrayUtils.findMax([1, 5, 3, 2]);\n * ```\n */\n\n/**\n * Options for array comparison operations\n */\ntype CompareOptions = {\n /** If true, elements must be in the same order. Defaults to false */\n ordered?: boolean;\n\n /** If true, performs deep equality comparison. Defaults to false */\n deep?: boolean;\n};\n\n/**\n * Represents an entity with an ID field\n */\ntype EmbeddedEntity = {\n /** Unique identifier for the entity */\n id: string;\n /** Additional properties of the entity */\n [key: string]: any;\n};\n\n/**\n * Types that can be compared using standard comparison operators\n */\ntype Comparable = string | number | boolean;\n\n/**\n * Collection of array utility functions\n */\nexport const ArrayUtils = {\n /**\n * Calculates the average of all numbers in an array\n * @param arr - Array of numbers to calculate average from\n * @returns The average of all numbers, or 0 if array is empty\n * @example\n * ```typescript\n * const avg = ArrayUtils.average([1, 2, 3, 4, 5]); // Returns 3\n * ```\n */\n average(arr: number[]): number {\n if (!Array.isArray(arr) || arr.length === 0) return 0;\n return this.sumArray(arr) / arr.length;\n },\n\n /**\n * Compares two arrays for equality by sorting and comparing elements\n * @param a1 - First array to compare\n * @param a2 - Second array to compare\n * @returns True if arrays contain the same elements in any order\n * @example\n * ```typescript\n * const equal = ArrayUtils.arrayEquals([1, 2, 3], [3, 2, 1]); // Returns true\n * ```\n */\n arrayEquals<T extends Comparable>(a1: T[], a2: T[]): boolean {\n if (!Array.isArray(a1) || !Array.isArray(a2)) return false;\n if (a1.length !== a2.length) return false;\n\n const sortedA1 = [...a1].sort(this.sortCompare);\n const sortedA2 = [...a2].sort(this.sortCompare);\n return sortedA1.every((v, i) => v === sortedA2[i]);\n },\n\n /**\n * Splits an array into chunks of specified size\n * @param arr - Array to split into chunks\n * @param size - Size of each chunk (must be positive)\n * @returns Array of arrays, each of size 'size'\n * @throws Error if size is not positive\n */\n chunks<T>(arr: T[], size: number): T[][] {\n if (!Number.isInteger(size) || size <= 0) {\n throw new Error(\"Chunk size must be a positive integer\");\n }\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n },\n\n /**\n * Compares two arrays for equality based on the given options\n * @param arr1 - First array to compare\n * @param arr2 - Second array to compare\n * @param options - Comparison options\n * @returns True if arrays are equal based on the options\n */\n compareArrays<T>(\n arr1: T[],\n arr2: T[],\n options: CompareOptions = {}\n ): boolean {\n if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;\n const { ordered = false, deep = false } = options;\n\n if (arr1.length !== arr2.length) return false;\n\n if (ordered) {\n return arr1.every((item, index) =>\n deep ? this.deepEqual(item, arr2[index]) : item === arr2[index]\n );\n } else {\n const visited: boolean[] = new Array(arr2.length).fill(false);\n\n return arr1.every((item1) => {\n const index = arr2.findIndex(\n (item2, i) =>\n !visited[i] &&\n (deep ? this.deepEqual(item1, item2) : item1 === item2)\n );\n if (index === -1) return false;\n visited[index] = true;\n return true;\n });\n }\n },\n\n /**\n * Returns a new array with unique values\n * @param array - Array to make unique\n * @returns Array with duplicate values removed\n */\n deduplicate<T>(array: T[]): T[] {\n if (!Array.isArray(array)) return [];\n return Array.from(new Set(array));\n },\n\n /**\n * Deep equality comparison between two values\n * @param a - First value\n * @param b - Second value\n * @returns True if values are deeply equal\n */\n deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n\n if (typeof a !== typeof b) return false;\n\n if (typeof a === \"object\" && a !== null && b !== null) {\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n if (Array.isArray(a)) {\n if (a.length !== (b as unknown[]).length) return false;\n return a.every((val, i) => this.deepEqual(val, (b as unknown[])[i]));\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b as Record<string, unknown>);\n\n if (keysA.length !== keysB.length) return false;\n\n return keysA.every((key) =>\n this.deepEqual(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key]\n )\n );\n }\n\n return false;\n },\n\n /**\n * Returns elements from array a that are not in array b based on id property\n * @param a - First array\n * @param b - Second array\n * @param getId - Optional function to extract id from items\n * @returns Array of elements from a that are not in b\n */\n difference<T>(\n a: T[],\n b: T[],\n getId: (item: T) => string | number = (item: any) => item.id\n ): T[] {\n const bIds = new Set(b.map(getId));\n return a.filter((item) => !bIds.has(getId(item)));\n },\n\n /**\n * Returns the maximum value in an array\n * @param arr - Array of comparable values\n * @returns Maximum value or undefined if array is empty\n */\n findMax<T extends Comparable>(arr: T[]): T | undefined {\n if (!Array.isArray(arr) || arr.length === 0) return undefined;\n return arr.reduce((max, val) => (val > max ? val : max), arr[0]);\n },\n\n /**\n * Returns the minimum value in an array\n * @param arr - Array of comparable values\n * @returns Minimum value or undefined if array is empty\n */\n findMin<T extends Comparable>(arr: T[]): T | undefined {\n if (!Array.isArray(arr) || arr.length === 0) return undefined;\n return arr.reduce((min, val) => (val < min ? val : min), arr[0]);\n },\n\n /**\n * Finds and updates an item in a collection based on id\n * @param collection - Collection to update\n * @param item - Item to update\n * @returns Updated collection\n * @throws Error if item is not found\n */\n findAndUpdate(\n collection: EmbeddedEntity[],\n item: EmbeddedEntity\n ): EmbeddedEntity[] {\n const index = collection.findIndex((b) => b.id === item.id);\n if (index === -1) {\n throw new Error(`Item with id ${item.id} not found in collection`);\n }\n return collection.map((element, i) => (i === index ? item : element));\n },\n\n /**\n * Flattens a nested array to a specified depth\n * @param arr - Array to flatten\n * @param depth - Maximum depth to flatten (default: Infinity)\n * @returns Flattened array\n */\n flatten<T>(arr: T[], depth = Infinity): T[] {\n if (depth <= 0) return arr.slice();\n if (!Array.isArray(arr)) return [arr];\n\n return arr.reduce<T[]>((acc, val) => {\n if (Array.isArray(val)) {\n acc.push(...this.flatten(val, depth - 1));\n } else {\n acc.push(val);\n }\n return acc;\n }, []);\n },\n\n /**\n * Groups array elements by a key or function\n * @param arr - Array to group\n * @param keyOrFn - Key to group by or function that returns the group key\n * @returns Object with grouped arrays\n */\n groupBy<T>(\n arr: T[],\n keyOrFn: keyof T | ((item: T) => string | number)\n ): Record<string, T[]> {\n if (!Array.isArray(arr)) return {};\n\n return arr.reduce((groups, item) => {\n const key =\n typeof keyOrFn === \"function\" ? keyOrFn(item) : String(item[keyOrFn]);\n\n groups[key] = groups[key] || [];\n groups[key].push(item);\n return groups;\n }, {} as Record<string, T[]>);\n },\n\n /**\n * Checks if two arrays have any common elements\n * @param array1 - First array\n * @param array2 - Second array\n * @returns True if arrays share at least one common element\n */\n hasCommonElement<T>(array1: T[], array2: T[]): boolean {\n if (!array1?.length || !array2?.length) return false;\n\n const [smaller, larger] =\n array1.length < array2.length ? [array1, array2] : [array2, array1];\n\n const set = new Set(smaller);\n return larger.some((element) => set.has(element));\n },\n\n /**\n * Returns the intersection of two arrays\n * @param arr1 - First array\n * @param arr2 - Second array\n * @returns Array containing elements present in both arrays\n */\n intersection<T>(arr1: T[], arr2: T[]): T[] {\n if (!Array.isArray(arr1) || !Array.isArray(arr2)) return [];\n const set = new Set(arr2);\n return arr1.filter((item) => set.has(item));\n },\n\n /**\n * Moves an item from one position to another in an array\n * @param arr - Array to modify\n * @param from - Source index\n * @param to - Destination index\n * @returns New array with item moved\n * @throws Error if indices are out of bounds\n */\n moveItem<T>(arr: T[], from: number, to: number): T[] {\n if (!Array.isArray(arr)) {\n throw new Error(\"First argument must be an array\");\n }\n if (from < 0 || from >= arr.length) {\n throw new Error(`Source index ${from} is out of bounds`);\n }\n if (to < 0 || to >= arr.length) {\n throw new Error(`Destination index ${to} is out of bounds`);\n }\n\n const newArr = [...arr];\n const [item] = newArr.splice(from, 1);\n newArr.splice(to, 0, item);\n return newArr;\n },\n\n /**\n * Returns a random element from the array\n * @param arr - Array to get element from\n * @returns Random element or undefined if array is empty\n */\n random<T>(arr: T[]): T | undefined {\n if (!Array.isArray(arr) || arr.length === 0) return undefined;\n return arr[Math.floor(Math.random() * arr.length)];\n },\n\n /**\n * Removes elements from an array that match a predicate\n * @param arr - Array to remove elements from\n * @param predicate - Function that returns true for elements to remove\n * @returns New array with matching elements removed\n */\n remove<T>(arr: T[], predicate: (item: T) => boolean): T[] {\n if (!Array.isArray(arr)) return [];\n return arr.filter((item) => !predicate(item));\n },\n\n /**\n * Returns a new array with elements in random order\n * @param arr - Array to shuffle\n * @returns New array with elements in random order\n */\n shuffle<T>(arr: T[]): T[] {\n if (!Array.isArray(arr)) return [];\n const result = [...arr];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n },\n\n /**\n * Compares two values for sorting\n * @param x - First value to compare\n * @param y - Second value to compare\n * @returns -1 if x < y, 0 if equal, 1 if x > y\n */\n sortCompare(x: Comparable, y: Comparable): number {\n const pre = [\"string\", \"number\", \"bool\"];\n\n if (typeof x !== typeof y) {\n return pre.indexOf(typeof y) - pre.indexOf(typeof x);\n }\n\n if (x === y) {\n return 0;\n }\n return x > y ? 1 : -1;\n },\n\n /**\n * Returns the sum of all numbers in an array\n * @param arr - Array of numbers\n * @returns Sum of all numbers\n */\n sumArray(arr: number[]): number {\n if (!Array.isArray(arr)) return 0;\n return arr.reduce((sum, num) => sum + (Number(num) || 0), 0);\n },\n\n /**\n * Returns the first n elements of an array\n * @param arr - Array to get elements from\n * @param n - Number of elements to get (default: 1)\n * @returns Array containing the first n elements\n */\n takeFirst<T>(arr: T[], n = 1): T[] {\n if (!Array.isArray(arr)) return [];\n return arr.slice(0, n);\n },\n\n /**\n * Returns the last n elements of an array\n * @param arr - Array to get elements from\n * @param n - Number of elements to get (default: 1)\n * @returns Array containing the last n elements\n */\n takeLast<T>(arr: T[], n = 1): T[] {\n if (!Array.isArray(arr)) return [];\n return arr.slice(-n);\n },\n\n /**\n * Returns the union of multiple arrays\n * @param arrays - Arrays to union\n * @returns Array containing unique elements from all arrays\n */\n union<T>(...arrays: T[][]): T[] {\n return this.deduplicate(arrays.flat());\n },\n};\n"],"names":[],"mappings":"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"}