Tengo una matriz que contiene detalles de los transportistas:
const carrier=[ {"carrier_code":"ups","items":0,"printable":0}, {"carrier_code":"dhl","items":0,"printable":0}, {"carrier_code":"tnt","items":0,"printable":0} ];
Luego otra matriz que contiene órdenes:
const orders = [ {"order_id":"00101","carrier_code":"dhl","printable":0}, {"order_id":"00101","carrier_code":"ups","printable":1}, {"order_id":"00101","carrier_code":"dhl","printable":1}, {"order_id":"00101","carrier_code":"dhl","printable":1}, {"order_id":"00101","carrier_code":"ups","printable":1}, {"order_id":"00101","carrier_code":"ups","printable":0}, {"order_id":"00101","carrier_code":"ups","printable":1}, {"order_id":"00101","carrier_code":"ups","printable":1} ];
Quiero actualizar items
y valores printable
en carrier
de manera de tener
carrier=[ {"carrier_code":"ups","items":5,"printable":4}, {"carrier_code":"dhl","items":3,"printable":2}, {"carrier_code":"tnt","items":0,"printable":0} ];
Pude lograr un resultado similar usando map/filter/reduce, pero para una situación con un objeto y una matriz.
Mientras que para esta situación solo puedo pensar en un forEach
anidado:
carriers.forEach(c => { orders.forEach(o => { c.items+=o.carrier_code==c.carrier_code?1:0; c.printable+=o.carrier_code==c.carrier_code&&o.printable==1?1:0; } ) }); console.log(carriers)
Pero tal vez esta es una solución ES6
Me preguntaba si ES9 podría ofrecer una solución "mejor",
¿Alguien puede sugerir una forma más fácil o más elegante de lograr el mismo resultado?
Para reducir la complejidad computacional, primero agrupe el carrier
por carrier_code
, luego puede iterar sobre los orders
y buscar la coincidencia inmediatamente ( O(n)
en lugar de O(n ^ 2)
).
Object.fromEntries
se puede usar para agrupar los transportistas, que es de ES2019.
const carrier=[{carrier_code:"ups",items:0,printable:0},{carrier_code:"dhl",items:0,printable:0},{carrier_code:"tnt",items:0,printable:0}],orders=[{order_id:"00101",carrier_code:"dhl",printable:0},{order_id:"00101",carrier_code:"ups",printable:1},{order_id:"00101",carrier_code:"dhl",printable:1},{order_id:"00101",carrier_code:"dhl",printable:1},{order_id:"00101",carrier_code:"ups",printable:1},{order_id:"00101",carrier_code:"ups",printable:0},{order_id:"00101",carrier_code:"ups",printable:1},{order_id:"00101",carrier_code:"ups",printable:1}]; const carrierByCode = Object.fromEntries( carrier.map(c => [c.carrier_code, c]) ); for (const order of orders) { const carrier = carrierByCode[order.carrier_code]; carrier.items++; if (order.printable) carrier.printable++; } console.log(carrier);
No hay nada en la especificación que convierta esto en una llamada única (más o menos), pero sin duda puede reducir esa complejidad O(n * m)
a una complejidad O(n + m)
contando primero sus pedidos y luego asignando esos conteos a su transportistas:
const counters = {}; // run your bin counting in O(n) orders.forEach({carrier_code} => { if (counters[carrier_code] === undefined) { counters[carrier_code] = 0; } counters[carrier_code]++; }); // And then assign those counts in O(m) carriers.forEach(c => (c.items = counters[c.carrier_code]));
Primero contaría y sumaría los artículos que necesito y luego los asignaría al transportista correspondiente. Esto es lo que haría:
const carrier = [ { carrier_code: "ups", items: 0, printable: 0 }, { carrier_code: "dhl", items: 0, printable: 0 }, { carrier_code: "tnt", items: 0, printable: 0 } ]; const orders = [ { order_id: "00101", carrier_code: "dhl", printable: 0 }, { order_id: "00101", carrier_code: "ups", printable: 1 }, { order_id: "00101", carrier_code: "dhl", printable: 1 }, { order_id: "00101", carrier_code: "dhl", printable: 1 }, { order_id: "00101", carrier_code: "ups", printable: 1 }, { order_id: "00101", carrier_code: "ups", printable: 0 }, { order_id: "00101", carrier_code: "ups", printable: 1 }, { order_id: "00101", carrier_code: "ups", printable: 1 } ]; var counts = orders.reduce((p, c) => { if (!p.hasOwnProperty(c.carrier_code)) p[c.carrier_code] = { items: 0, printable: 0 }; p[c.carrier_code].items++; p[c.carrier_code].carrier_code=c.carrier_code; p[c.carrier_code].printable += c.printable; return p; }, {}); carrier.forEach((e, index) => carrier[index] = counts[e.carrier_code] || carrier[index]); console.log(carrier);