0

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

3 Answers 3

1

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);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot.. I did not thought to use findIndex, but I would have not found such solution. I selected this solution because it returns me an array that I can directly pass to datatable, although, probably, other solutions return a more formal correctly solution
0

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
    }
  }
}

Comments

0

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));

2 Comments

Cool - I haven't seen reduce used like that before. Thx
I'm not sure how you want to handle multiple CODAmount or boxes values ... you can quite easily sum them up within the reduce, or accumulate multiples in an array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.