I have an array of Orders and I need to group them according to the carrierCode:
const orders = [
{
"depo": "Berlin",
"boxes": 1,
"isCOD": true,
"CODAmount": 45.33,
"carrierCode": "ups",
"sid": "DCAC298A627DF2D1980D23F67F05E8E4",
},
{
"depo": "Leipzig",
"boxes": 2,
"isCOD": false,
"CODAmount": 0,
"carrierCode": "tnt",
"sid": "8BF93B9159742250CA7F73304808E316",
},
{
"depo": "Leipzig",
"boxes": 2,
"isCOD": true,
"CODAmount": 124.00,
"carrierCode": "dhl",
"sid": "0DC1A9BCFA6C5834361AFABBD857CEDD",
},
{
"depo": "Leipzig",
"boxes": 3,
"isCOD": true,
"CODAmount": 415.33,
"carrierCode": "tnt",
"sid": "8BF93B9159742250CA7F73304808E316",
},
{
"depo": "Berlin",
"boxes": 1,
"isCOD": false,
"CODAmount": 0,
"carrierCode": "tnt",
"sid": "0DC1A9BCFA6C5834361AFABBD857CEDD",
}
];
so far I did this:
var groups = orders.reduce((p, c) => {
var code = c.carrierCode;
if (!p.hasOwnProperty(code)) {
p[code] = 0;
}
p[code]++;
return p;
}, {});
console.log(groups);
var countsExtended = Object.keys(groups).map(k => {
return {code: k, orderscount: groups[k]}; });
console.log(countsExtended);
that returns
{ ups: 1, tnt: 3, dhl: 1 }
and
[
{ code: 'ups', orderscount: 1 },
{ code: 'tnt', orderscount: 3 },
{ code: 'dhl', orderscount: 1 }
]
but now I need to group also by depo and 'import' some other values from orders like boxes count, and total COD Amount: practically, and I should get something like this
[
{ code: 'ups', orderscount: 1, depo:'Berlin', boxes: 1, CODAmount: 45.33},
{ code: 'tnt', orderscount: 1, depo:'Berlin', boxes: 1, CODAmount: 0.00},
{ code: 'tnt', orderscount: 2, depo:'Leipzig', boxes: 5, CODAmount: 415.33},
{ code: 'dhl', orderscount: 1, depo:'Leipzig', boxes: 2, CODAmount: 124.00}
]
how can I get this with ES6/ES10?
Thanks
Here's a way to leverage just that first reduce() function, along with a spread operator to get what you need.
const orders = [{ depo: 'Berlin', boxes: 1, isCOD: true, CODAmount: 45.33, carrierCode: 'ups', sid: 'DCAC298A627DF2D1980D23F67F05E8E4', }, { depo: 'Leipzig', boxes: 2, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Leipzig', boxes: 2, isCOD: true, CODAmount: 124.0, carrierCode: 'dhl', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', }, { depo: 'Leipzig', boxes: 3, isCOD: true, CODAmount: 415.33, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Berlin', boxes: 1, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', },];
const groups = orders.reduce((p, c) => {
delete c.sid;
delete c.isCOD;
let index = p.findIndex(pi => pi.carrierCode == c.carrierCode && pi.depo == c.depo);
if (index > -1) {
p[index].ordercounts++;
p[index].CODAmount+=+c.CODAmount;
p[index].boxes+=+c.boxes;
}
else p.push({ ...c, ordercounts: 1});
return p;
}, []);
console.log(groups);
You don't need to do anything extra, you can simply capture all the properties that you want in the final objects within your reduce().
Here isolating properties using destructuring and simplifying the logic a little with logical nullish assignment (??=)
const orders = [{ depo: 'Berlin', boxes: 1, isCOD: true, CODAmount: 45.33, carrierCode: 'ups', sid: 'DCAC298A627DF2D1980D23F67F05E8E4', }, { depo: 'Leipzig', boxes: 2, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Leipzig', boxes: 2, isCOD: true, CODAmount: 124.0, carrierCode: 'dhl', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', }, { depo: 'Leipzig', boxes: 3, isCOD: true, CODAmount: 415.33, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Berlin', boxes: 1, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', },];
const groups = Object.values(
orders.reduce((p, { carrierCode: code, depo, boxes, CODAmount }) => {
p[code] ??= { code, orderscount: 0, depo: {} };
p[code]['depo'][depo] ??= { depo, boxes: 0, CODAmount: 0 };
p[code]['depo'][depo].boxes += boxes;
p[code]['depo'][depo].CODAmount += CODAmount;
p[code].orderscount += 1;
return p;
}, {})
).map(({ depo, ...rest }) => ({ ...rest, depo: Object.values(depo) }));
console.log(Object.values(groups));
To create a flat array as in the accepted answer you can simply use the same logic but with a composite key made of depo and carrierCode.
const orders = [{ depo: 'Berlin', boxes: 1, isCOD: true, CODAmount: 45.33, carrierCode: 'ups', sid: 'DCAC298A627DF2D1980D23F67F05E8E4', }, { depo: 'Leipzig', boxes: 2, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Leipzig', boxes: 2, isCOD: true, CODAmount: 124.0, carrierCode: 'dhl', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', }, { depo: 'Leipzig', boxes: 3, isCOD: true, CODAmount: 415.33, carrierCode: 'tnt', sid: '8BF93B9159742250CA7F73304808E316', }, { depo: 'Berlin', boxes: 1, isCOD: false, CODAmount: 0, carrierCode: 'tnt', sid: '0DC1A9BCFA6C5834361AFABBD857CEDD', },];
const groups = Object.values(
orders.reduce((p, { carrierCode: code, depo, boxes, CODAmount }) => {
const key = `${code}_${depo}`;
p[key] ??= { code, depo, orderscount: 0, boxes: 0, CODAmount: 0 };
p[key].orderscount += 1;
p[key].boxes += boxes;
p[key].CODAmount += CODAmount;
return p;
}, {})
);
console.log(Object.values(groups));
I put the result in a bit different structure
const result = {};
orders.forEach(({ carrierCode, depo, boxes, CODAmount }) => {
if (!result[carrierCode]) {
result[carrierCode] = {};
}
if (!result[carrierCode][depo]) {
result[carrierCode][depo] = { boxes, CODAmount, orderscount: 1 };
} else {
result[carrierCode][depo].boxes += boxes;
result[carrierCode][depo].CODAmount += CODAmount;
result[carrierCode][depo].orderscount++;
}
});
Result:
{
"ups": {
"Berlin": {
"boxes": 1,
"CODAmount": 45.33,
"orderscount": 1
}
},
"tnt": {
"Leipzig": {
"boxes": 5,
"CODAmount": 415.33,
"orderscount": 2
},
"Berlin": {
"boxes": 1,
"CODAmount": 0,
"orderscount": 1
}
},
"dhl": {
"Leipzig": {
"boxes": 2,
"CODAmount": 124,
"orderscount": 1
}
}
}