Home > Blockchain >  ES6 / ES9 group array of objects by multiple parameters
ES6 / ES9 group array of objects by multiple parameters

Time:12-01

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

CodePudding user response:

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);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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));
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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