Tengo debajo de la matriz json que quiero agrupar según la clave de combinación sourceno y destno.
Código actual:
let eddarr=[ { "sourceno": "112", "destno": "321", "edno": "123", "eppno": "322" }, { "sourceno": "112", "destno": "321", "edno": "123", "eppno": "324" }, { "sourceno": "114", "destno": "335", "edno": "100", "eppno": "355" }, { "sourceno": "114", "destno": "335", "edno": "222", "eppno": "999" } ] let pobj={} let p_data=[] let count=0; for(key in eddarr) { let resultarr=eddarr[key] let pkey = eddarr[key].sourceno+'-'+eddarr[key].destno; let obj = {}; let isNew = true; if(pdata.length > 0){ for(let j=0;j<pdata.length;j++){ if(pdata[j].hasOwnProperty(pkey)){ pdata[j][pkey][pdata[j][pkey].length] = resultarr; isNew = false; break; } } } if(isNew){ obj[pkey] = new Array(); obj[pkey][0] = resultarr; pdata.push(obj); } console.log(pdata)El código anterior funciona bien y obtengo el resultado inferior, pero se está ejecutando muy lentamente, está creando el resultado inferior para registros de 37K después de 15 minutos. ¿Cómo puedo optimizar este código o cualquier otra necesidad lógica para construir? Quiero procesar 1,5 millones de registros, pero el bucle tarda demasiado.
El resultado final después del procesamiento debería ser así:
[ { "112-321": [ { "edno": "123", "eppno": "322" }, { "edno": "123", "eppno": "324" } ] }, { "114-335": [ { "edno": "100", "eppno": "355" }, { "edno": "222", "eppno": "999" } ] } ]Podría desestructurar el objeto para omitir claves y construir un solo objeto con claves de agrupación. A partir de esto, construya una matriz de objetos con una sola propiedad.
const data = [{ sourceno: "112", destno: "321", edno: "123", eppno: "322" }, { sourceno: "112", destno: "321", edno: "123", eppno: "324" }, { sourceno: "114", destno: "335", edno: "100", eppno: "355" }, { sourceno: "114", destno: "335", edno: "222", eppno: "999" }], keys = ['sourceno', 'destno'], result = Object .entries(data.reduce((r, o) => { const key = keys.map(k => { let v; ({ [k]: v, ...o } = o); return v; }).join('-'); (r[key] ??= []).push(o); return r; }, {})) .map(pair => Object.fromEntries([pair])); console.log(result); .as-console-wrapper { max-height: 100% !important; top: 0; }Una solución más rápida, en comparación con la que propuse antes, sería usar un objeto para realizar un seguimiento de los elementos insertados en pdata ; de esta manera puedes lograr tu objetivo atravesando eddarr solo una vez.
Tenga en cuenta que en el siguiente fragmento de código estoy usando un IIFE para evitar "contaminar" el alcance global con la variable itemsListObj , pero eso no es estrictamente necesario.
const eddarr = [{ "sourceno": "112", "destno": "321", "edno": "123", "eppno": "322" }, { "sourceno": "112", "destno": "321", "edno": "123", "eppno": "324" }, { "sourceno": "114", "destno": "335", "edno": "100", "eppno": "355" }, { "sourceno": "114", "destno": "335", "edno": "222", "eppno": "999" } ]; const pdata = (function() { const itemsListObj = {}; return eddarr.reduce((acc, { sourceno, destno, edno, eppno }) => { const key = `${sourceno}-${destno}`; const insertIndex = itemsListObj[key]; if (insertIndex != null) { acc[insertIndex][key].push({ edno, eppno }); } else { acc.push({ [key]: [{ edno, eppno }] }); itemsListObj[key] = acc.length - 1; } return acc; }, []); })() console.log(pdata); const values = {}; eddarr = [{ sourceno: "112", destno: "321", edno: "123", eppno: "322" }, { sourceno: "112", destno: "321", edno: "123", eppno: "324" }, { sourceno: "114", destno: "335", edno: "100", eppno: "355" }, { sourceno: "114", destno: "335", edno: "222", eppno: "999" }]; eddarr.map((entry) => { var key = entry.sourceno + '-' + entry.destno; if (!values[ key ]) { values[ key ] = []; } values[ key ].push({ edno: entry.edno, eppno: entry.eppno }) }); console.log(Object.keys(values).map(key => { return { [ key ]: values[key] } }));