ES6 / ES9 通过多个参数对对象数组进行分组

ES6 / ES9 group array of objects by multiple parameters

我有一个订单数组,我需要根据 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",
    }
];

到目前为止我这样做了:

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

那个returns

{ ups: 1, tnt: 3, dhl: 1 }

[ 
    { code: 'ups', orderscount: 1 },
    { code: 'tnt', orderscount: 3 },
    { code: 'dhl', orderscount: 1 }
]

但现在我还需要按 depo 和 'import' 订单中的一些其他值进行分组,例如箱数和 COD 总金额:实际上,我应该得到这样的结果

[ 
    { 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}
]

如何使用 ES6/ES10 获得此信息?

谢谢

这里有一种方法可以利用第一个 reduce() 函数,以及一个扩展运算符来获得您需要的东西。

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

您不需要做任何额外的事情,您只需在 reduce().

的最终对象中捕获您想要的所有属性

此处使用 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));

要按照已接受的答案创建平面数组,您可以简单地使用相同的逻辑,但使用由 depocarrierCode.

组成的复合键

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

我把结果放在有点不同的结构中

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

结果:

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