/** * 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 { return array.reduce( (groups, item) => { const key = keyFn(item); (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;