tipazo
Version:
libreria-multiform
137 lines (116 loc) • 4.88 kB
text/typescript
//elimina los duplicados
export function removeAdvancedDuplicates<T>(arr: T[]): T[] {
const seen = new Set<string>();
return arr.filter(item => {
const key = JSON.stringify(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
//muestra los duplicados
export function findDuplicates<T>(arr: T[]): T[] {
const seen = new Set<string>();
const duplicates: T[] = [];
for (const item of arr) {
const key = JSON.stringify(item);
if (seen.has(key)) {
duplicates.push(item);
} else {
seen.add(key);
}
}
return duplicates;
}
//cuenta duplicado
export function countDuplicates<T>(arr: T[]): Map<string, number> {
const countMap = new Map<string, number>();
for (const item of arr) {
const key = JSON.stringify(item);
countMap.set(key, (countMap.get(key) || 0) + 1);
}
return countMap;
}
export function countTotalDuplicates<T>(arr: T[]): number {
const seen = new Set<string>();
let duplicateCount = 0;
for (const item of arr) {
const key = JSON.stringify(item);
if (seen.has(key)) {
duplicateCount++;
} else {
seen.add(key);
}
}
return duplicateCount;
}
export function agruparPorClave<T extends Record<string, any>>(datos: T[], clave: string): Record<string, T[]> {
return datos.reduce((grupo, item) => {
const valor = item[clave];
if (!grupo[valor]) grupo[valor] = [];
grupo[valor].push(item);
return grupo;
}, {} as Record<string, T[]>);
}
export function resumenNumerico(datos: Record<string, any>[], clave: string) {
const valores = datos.map(d => d[clave]).filter(v => typeof v === 'number');
const total = valores.reduce((a, b) => a + b, 0);
const promedio = total / valores.length;
const max = Math.max(...valores);
const min = Math.min(...valores);
return { total, promedio, max, min };
}
export function filtrarPorRangoDeFechas(
datos: Record<string, any>[],
claveFecha: string,
desde: Date,
hasta: Date
): Record<string, any>[] {
return datos.filter(item => {
const fecha = new Date(item[claveFecha]);
return fecha >= desde && fecha <= hasta;
});
}
export function detectarOutliers<T extends Record<string, any>>(datos: T[], clave: string): T[] {
const valores = datos.map(d => d[clave]).filter(v => typeof v === 'number').sort((a, b) => a - b);
const q1 = valores[Math.floor(valores.length / 4)];
const q3 = valores[Math.floor((valores.length * 3) / 4)];
const iqr = q3 - q1;
const min = q1 - 1.5 * iqr;
const max = q3 + 1.5 * iqr;
return datos.filter(d => {
const valor = d[clave];
return typeof valor === 'number' && (valor < min || valor > max);
});
}
export function generarResumenNarrativo<T extends Record<string, any>>(datos: T[], claveNombre: string, claveValor: string): string {
if (!datos.length) return 'No hay datos disponibles para generar el resumen.';
const total = datos.reduce((sum, item) => sum + item[claveValor], 0);
const promedio = total / datos.length;
const ordenados = [...datos].sort((a, b) => b[claveValor] - a[claveValor]);
const top = ordenados[0];
const lista = datos.map(d => `${d[claveNombre]} (${d[claveValor]})`).join(', ');
return `Durante el período analizado, el producto más vendido fue ${top[claveNombre]} con un total de ${top[claveValor]}. Los demás productos incluyen: ${lista}. El total de ventas fue de ${total}, con un promedio de ${promedio.toFixed(2)} por producto.`;
}
export function generarInsightAutomático<T extends Record<string, any>>(datos: T[], claveNumerica: string, claveGrupo?: string): string {
if (!datos.length) return 'No hay datos disponibles para generar insights.';
const valores = datos.map(d => d[claveNumerica]).filter(v => typeof v === 'number');
const total = valores.reduce((a, b) => a + b, 0);
const promedio = total / valores.length;
const max = Math.max(...valores);
const min = Math.min(...valores);
let mensaje = `Se analizaron ${valores.length} registros. El total acumulado es ${total}, con un promedio de ${promedio.toFixed(2)}. El valor máximo fue ${max} y el mínimo ${min}.`;
if (claveGrupo) {
const grupos = agruparPorClave(datos, claveGrupo);
const grupoTop = Object.entries(grupos).sort((a, b) => {
const sumaA = a[1].reduce((sum, item) => sum + item[claveNumerica], 0);
const sumaB = b[1].reduce((sum, item) => sum + item[claveNumerica], 0);
return sumaB - sumaA;
})[0];
mensaje += ` El grupo con mayor contribución fue "${grupoTop[0]}" con ${grupoTop[1].length} registros.`;
}
if (max > promedio * 2) {
mensaje += ` ⚠️ Se detectó un valor excepcionalmente alto que podría indicar un outlier o una anomalía.`;
}
return mensaje;
}