UNPKG

my-utils-kit

Version:

A lightweight and type-safe utility library for working with strings, objects, array Performance methods in TypeScript. Includes helpful methods for deep cloning, object transformations, safe access, query string handling, and more — designed for modern J

343 lines (273 loc) 9.65 kB
export function removeSortedDuplicates<T>(arr:T[]) { let left = 0; for(let right = 1; right < arr.length; right++) { if(arr[left] !== arr[right]) { arr[++left] = arr[right]; } } return arr.slice(0,left + 1); } export function removeUnsortedDuplicates<T>(arr:T[]) { return [...new Set(arr)] } export function flattenArray<T>(arr:T[], depth = Infinity) { return arr.flat(depth); } export function chunk<T>(arr:T[],size:number) { if(!arr) throw new Error('Input must be an array'); if(size <= 0) throw new Error('chunk size must be greater than zero'); let res:T[][] = []; for(let i=0; i<arr.length; i=i+size) { res.push(arr.slice(i,i+size)); } return res; } export function differences<T>(arr1: T[], arr2: T[]) { if(!arr1 || !arr2) throw new Error('Input must be an array'); let set1 = new Set(arr1); let set2 = new Set(arr2); let left:T[] = []; let right:T[] = []; let i = 0; let j = 0; while (i < arr1.length || j < arr2.length) { if (j < arr2.length && !set1.has(arr2[j])) { right.push(arr2[j]); } if (i < arr1.length && !set2.has(arr1[i])) { left.push(arr1[i]); } j++; i++; } return [...left, ...right]; } export function intersection<T>(arr1: T[], arr2: T[]) { if(!arr1 || !arr2) throw new Error('Input must be an array'); let set = new Set(arr2); let res:T[] = []; for(let i=0; i<arr1.length; i++) { if(set.has(arr1[i])) { res.push(arr1[i]); set.delete(arr1[i]) } } return res; } export function union<T>(arr1: T[], arr2: T[]) { if(!arr1 || !arr2) throw new Error('Input must be an array'); let mergedArr = [...arr1, ...arr2] return Array.from(new Set(mergedArr)) } export function combineElementWise(arr1: number[], arr2: number[]): number[] { const result: number[] = []; for (let i = 0; i < arr1.length; i++) { result.push(arr1[i] + arr2[i]); } return result; } export function unzip<T, U>(arr: [T, U][]): [T[], U[]] { const firstArr = arr.map(pair => pair[0]); // Extract first elements const secondArr = arr.map(pair => pair[1]); // Extract second elements return [firstArr, secondArr]; } export function partitionByCondition<T>(arr: T[], predicate: (value: T) => boolean): [T[], T[]] { const pass: T[] = []; const fail: T[] = []; for (const item of arr) { if (predicate(item)) { pass.push(item); } else { fail.push(item); } } return [pass, fail]; } export function sortBy<T>(arr: T[], key: keyof T, order: 'asc' | 'desc' = 'asc'): T[] { return arr.sort((a, b) => { if (a[key] < b[key]) { return order === 'asc' ? -1 : 1; } if (a[key] > b[key]) { return order === 'asc' ? 1 : -1; } return 0; // If equal }); } export function countOccurencesArr<T>(arr: T[], char: T) { if(!arr) throw new Error('Input must be an array'); let left = 0; let right = arr.length - 1; let count = 0; while (left <= right) { if (arr[left] === char) count++; if (arr[right] === char && left !== right) count++; left++; right--; } if (left === right && arr[left] === char) count++; return count; } export function removeFalsy<T>(arr: T[]) { if(!arr) throw new Error('Input must be an array'); return arr.filter(item => Boolean(item)) } export function move<T>(arr: T[], from: number, to: number): T[] { if (!Array.isArray(arr)) throw new Error("Input must be an array"); if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) throw new Error("Invalid from/to index"); const element = arr[from]; arr.splice(from, 1); arr.splice(to, 0, element); return arr; } export function reverseShallow<T>(arr: T[]): T[] { return [...arr].reverse(); } export function reverseDeep<T>(arr: T[]): T[] { return JSON.parse(JSON.stringify([...arr])).reverse(); } export function reverseRange<T>(arr:T[],start:number, end:number) { let newArr = [...arr] let reverseArr = newArr.slice(start,end+1).reverse(); let deleteCount = end - start; newArr.splice(start,deleteCount+1,...reverseArr); return newArr; } export function reverseWithCondition<T>(arr: T[], condition: (value: T, index: number) => boolean): T[] { const result = [...arr]; const indices = result .map((value, i) => condition(value, i) ? i : -1) .filter(i => i !== -1); let left = 0; let right = indices.length - 1; while (left < right) { const i = indices[left]; const j = indices[right]; [result[i], result[j]] = [result[j], result[i]]; left++; right--; } return result; } export function rotate<T>(arr: T[], k: number): T[] { const len = arr.length; if (len === 0) return []; k = k % len; if (k < 0) k += len; return [...arr.slice(-k), ...arr.slice(0, -k)]; } export function pluck<T, K extends keyof T>(arr: T[], key: K): T[K][] { return arr.map(item => item[key]); } export function fullyFlatten<T>(arr:T[]) { let res: T[] = []; for(let char of arr) { if(Array.isArray(char)) res.push(...fullyFlatten<T>(char)) else res.push(char); } return res; } export function getFirst<T>(arr: T[], k: number = 1): T[] { if (!Array.isArray(arr)) throw new Error('Input must be an array'); if (k <= 0) throw new Error('Number must be a positive value'); return arr.slice(0, k); } export function getLast<T>(arr: T[], k: number = 1): T[] { if (!Array.isArray(arr)) throw new Error('Input must be an array'); if (k <= 0) throw new Error('Number must be a positive value'); return arr.slice(-k); } export const compact = removeFalsy; export function arrayToObjects<T>(arr:[string, T][]) { const res: Record<string, T> = {}; for (let [key, value] of arr) { res[key] = value; } return res; } export function objectToArray<T>(obj:Record<string,T>) { let res: [string, T][] = []; for(let key in obj) { if(obj.hasOwnProperty(key)) res.push([key, obj[key]]) } return res; } export function range(start: number, end: number, step: number = 1): number[] { let result: number[] = []; for (let i = start; i <= end; i += step) { result.push(i); } return result; } export function sumArray<T extends number>(arr: T[]) { return arr.reduce((initial,val) => initial+val, 0) } export function getAverage<T extends number>(arr: T[]): number { if (arr.length === 0) throw new Error("Array cannot be empty"); return Math.floor(arr.reduce((initial, val) => initial + val, 0) / arr.length); } export function getMedian<T extends number>(arr: T[]): number { if (arr.length === 0) throw new Error("Array cannot be empty"); const sortedArr = [...arr].sort((a, b) => a - b); // Sort the array const mid = Math.floor(sortedArr.length / 2); // Find the middle index // If even length, return the average of the two middle elements if (sortedArr.length % 2 === 0) { return (sortedArr[mid - 1] + sortedArr[mid]) / 2; } // If odd length, return the middle element return sortedArr[mid]; } export function getMode<T extends number>(arr: T[]) { if (arr.length === 0) throw new Error("Array cannot be empty"); // Create a frequency map const frequencyMap: { [key: number]: number } = {}; for (let num of arr) { frequencyMap[num] = (frequencyMap[num] || 0) + 1; } // Find the maximum frequency const maxFrequency = Math.max(...Object.values(frequencyMap)); // Return all numbers that have the maximum frequency return Object.keys(frequencyMap) .filter(key => frequencyMap[Number(key)] === maxFrequency) .map(key => Number(key)); } export function isSorted<T extends number>(arr: T[], order: 'asc' | 'desc' = 'asc'): boolean { if (arr.length <= 1) return true; // A single-element array or empty array is considered sorted for (let i = 0; i < arr.length - 1; i++) { if (order === 'asc' && arr[i] > arr[i + 1]) { return false; // If elements are not in ascending order } if (order === 'desc' && arr[i] < arr[i + 1]) { return false; // If elements are not in descending order } } return true; // Array is sorted in the specified order } export function getNthElements<T>(arr: T[], n: number): T[] { if (n <= 0) throw new Error("n must be a positive integer"); return arr.filter((_, index) => index % n === n - 1); } export function findDuplicates<T>(arr: T[]): T[] { let seen = new Set<T>(); let duplicates: T[] = []; for (let item of arr) { if (seen.has(item)) { duplicates.push(item); // If already seen, add to duplicates } else { seen.add(item); // Otherwise, add to seen set } } return duplicates; } export function removeObjectDuplicates<T>(arr: T[], key: keyof T): T[] { let seen = new Set<any>(); // Set to store unique values based on the key return arr.filter(item => { if (seen.has(item[key])) { return false; // If we've already seen this value, exclude it } else { seen.add(item[key]); // Add the value to the seen set return true; // Keep the item } }); }