export function mapCombine( items: T[], property: keyof T, map: (item: T) => E, combine: (a: T, b: T) => E | undefined, ): E[] { // Helper function to check if a value is nullish const isNullish = (value: any): boolean => value === undefined || value === null || (typeof value === 'string' && value.trim() === ''); const result: Array<{ value: T | E; combined: boolean; skip: boolean; }> = items.map(item => ({ value: item, combined: false, skip: false })); for (let i = 0; i < result.length; i++) { if (result[i].combined || result[i].skip) continue; const propValueI = (result[i].value as T)[property]; if (isNullish(propValueI)) continue; // Skip items with nullish property values for (let j = i + 1; j < result.length; j++) { if (result[j].skip) continue; const propValueJ = (result[j].value as T)[property]; if (isNullish(propValueJ)) continue; // Skip if second item has nullish property if (propValueI === propValueJ) { const combinedValue = combine(result[i].value as T, result[j].value as T); if (combinedValue !== undefined) { result[i].value = combinedValue; result[i].combined = true; result[j].skip = true; break; } } } } return result .filter(item => !item.skip) .map(item => item.combined ? item.value as E : map(item.value as T)); } export function parseAmount(input?: string): number|undefined { if (input === undefined) { return undefined; } const v = Number.parseFloat(input.replaceAll(",", ".")); if (isNaN(v)) { return undefined; } return v; }