/** * Modern array utilities leveraging ES2024 features */ /** * Group array items by a key using ES2024 Object.groupBy * This is more efficient than manual grouping */ export function groupBy( array: T[], keyFn: (item: T) => K, ): Record { if ("groupBy" in Object) { return (Object as any).groupBy(array, keyFn); } return array.reduce( (groups, item) => { const key = keyFn(item); if (!groups[key]) { groups[key] = []; } groups[key].push(item); return groups; }, {} as Record, ); } /** * Chunk array into smaller arrays of specified size * Uses modern array methods for efficiency */ export function chunk(array: T[], size: number): T[][] { if (size <= 0) return []; const chunks: T[][] = []; for (let i = 0; i < array.length; i += size) { chunks.push(array.slice(i, i + size)); } return chunks; } /** * Get unique items from array with optional key function * Leverages Set for better performance */ export function unique(array: T[]): T[]; export function unique(array: T[], keyFn: (item: T) => K): T[]; export function unique(array: T[], keyFn?: (item: T) => K): T[] { if (!keyFn) { return [...new Set(array)]; } const seen = new Set(); return array.filter((item) => { const key = keyFn(item); if (seen.has(key)) { return false; } seen.add(key); return true; }); } /** * Safe array access using ES2024 .at() method * Returns undefined for out-of-bounds access */ export function safeAt(array: T[], index: number): T | undefined { return array.at?.(index) ?? array[index]; } /** * Partition array into two arrays based on predicate */ export function partition( array: T[], predicate: (item: T) => boolean, ): [T[], T[]] { const truthy: T[] = []; const falsy: T[] = []; for (const item of array) { if (predicate(item)) { truthy.push(item); } else { falsy.push(item); } } return [truthy, falsy]; } /** * Modern intersection of arrays */ export function intersection(...arrays: T[][]): T[] { if (arrays.length === 0) return []; if (arrays.length === 1) return [...arrays[0]]; const [first, ...rest] = arrays; const sets = rest.map((arr) => new Set(arr)); return first.filter((item) => sets.every((set) => set.has(item))); } /** * Safe array operations that return null on empty arrays */ export const SafeArray = { first: (array: T[]): T | null => array[0] ?? null, last: (array: T[]): T | null => array.at?.(-1) ?? array[array.length - 1] ?? null, random: (array: T[]): T | null => { if (array.length === 0) return null; return array[Math.floor(Math.random() * array.length)]; }, } as const;