Estoy usando este método para comparar dos matrices muy grandes de objetos para crear una matriz de resultados.
Estos arreglos pueden tener de 5 a 250,000 objetos, cada objeto tiene 8 propiedades. Las propiedades son todas cadenas (hasta 256 caracteres) y números enteros.
Se tarda más de 15 minutos en crear la matriz de resultados con 250 000 objetos.
Al darme cuenta de que la computadora, la memoria, la fase de la luna, etc., son todos factores, estaba buscando una manera mejor/más rápida.
Cualquier consejo apreciado :)
const arr1 = [{prop1: "foo", prop2: 100},{prop1: "bar", prop2: 101}] // 250,000 objects const arr2 = [{prop1: "foo", prop2: 50},{prop1: "bar", prop2: 51}] // 250,000 objects let final = [] for(let left of arr1) { for(let right of arr2) { if(left.prop1 === right.prop1 && left.prop2 < right.prop2) { final.push(left) break } } } }Un enfoque que consumirá más memoria pero tardará menos tiempo en ejecutarse será convertir una de las matrices en un objeto o mapa indexado por prop1 . De esa manera, en lugar de iterar sobre cada elemento para ver si coincide, simplemente busque el elemento de elementos para ese prop1 .
const arr2ByProp1 = new Map(); for (const item of arr2) { arr2ByProp1.set(item.prop1, item); } for (const item1 of arr1) { const item2 = arr2ByProp1.get(item1.prop1); if (item2 && item1.prop2 < item2.prop2) { final.push(item1); } } También puede modificar lo anterior para usar for(let i = 0, length = arr1.length; i < length; i++) { en su lugar (un poco más rápido, pero un poco más difícil de leer y entender de un vistazo). Se pueden hacer otros ajustes menores, pero no deberían tener mucho efecto en comparación con la mejora de la complejidad del tiempo.
Sin embargo, tener 250k elementos en la memoria para empezar es sospechoso. Si en cambio estuvieran en una base de datos, probablemente sería mucho más rápido consultar la base de datos (que puede encontrar por .prop1 y .prop2 ) para encontrar estas coincidencias que hacer las manipulaciones en JavaScript (lo que requiere reestructurar uno de los estructuras de datos completas primero, lo cual no es tan eficiente). Una base de datos también puede aprovechar la ejecución paralela, a diferencia de esta situación particular de JavaScript.
Usar mapas es realmente el camino a seguir. Nuestro diseño era terrible. Funcionó bien hasta que comenzamos a ver una gran cantidad de objetos.
Solo iterar objetos con forEach tomó de 10 a 15 minutos... 250 000 objetos x 250 000 objetos x 8 propiedades = 500 000 000 000 comparaciones.
El uso de un bucle for...of con interrupción tuvo un aumento insignificante en el rendimiento.
Refactorizado todo con mapas, se redujo a menos de 5 segundos (no es un tipo-o).
Increíble y gracias (@CertainPerformance)!
const mapA = new Map() // 250,000 objects const mapB = new Map() // 250,000 objects let mapC = new Map() // results mapA.forEach((v,k) => { if(mapB.has(k)) { const o = MapA.get(k) if(o.prop === v.prop) { mapC.set(k,v) } } })