如何在Javascript中基于多个键对对象数组进行分组?

5

我有以下数组

 [
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToCustomer",
    "TimeStart": "1970-01-01T06:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToCustomer",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToCustomer",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T05:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 2,
    "PostalCodeType": "ShipToCustomer",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 2,
    "PostalCodeType": "ShipToCustomer",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 3,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 3,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 4,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 4,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 5,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T16:22:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 5,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:23:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 6,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 6,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T06:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 1,
    "ShippingCarrierId": 1,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T05:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 2,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T00:00:00.000Z",
    "TimeEnd": "1970-01-01T15:59:00.000Z",
    "PickupTimeSlot": "PM",
    "DaysToAdd": 0,
    "PickupTime": "1970-01-01T17:00:00.000Z"
  },
  {
    "WarehouseId": 2,
    "ShippingCarrierId": 2,
    "PostalCodeType": "ShipToDS",
    "TimeStart": "1970-01-01T16:00:00.000Z",
    "TimeEnd": "1970-01-01T23:59:00.000Z",
    "PickupTimeSlot": "AM",
    "DaysToAdd": 1,
    "PickupTime": "1970-01-01T11:00:00.000Z"
  }
]

我希望按照WarehouseIdShippingCarrierId和邮政编码类型进行分组。每个对象将有Timestart、TimeEnd等子数组对象。
如何实现这一点?
输出结果类似于:
PickupTimeTable: [{
            WarehouseId: 1,
            ShippingCarrierId: 1,
            PostalCodeType: 'ShipToCustomer',
            PickupTimeSlots: [{
                    StartTime: '06:00:00.0000000',
                    EndTime: '15:59:00.0000000',
                    Slot: 'PM',
                    PickupTime: '17:00:00.0000000',
                    DaysToAdd: 0
                },
                {
                    StartTime: '16:00:00.0000000',
                    EndTime: '23:59:00.0000000',
                    Slot: 'AM',
                    PickupTime: '11:00:00.0000000',
                    DaysToAdd: 1
                },
                {
                    StartTime: '00:00:00.0000000',
                    EndTime: '05:59:00.0000000',
                    Slot: 'AM',
                    PickupTime: '11:00:00.0000000',
                    DaysToAdd: 0
                },
            ]
        }, ]

2
你的尝试是什么? - Jack Bashford
有很多方法可以解决这个问题。其中一种方法是使用 reduce 函数 更多细节请参见此处 - Imtk
创建一个对象数组,其中包含不同的 WarehouseId、ShippingCarrierId 和 PostalCodeType,并使用 foreach 循环添加对象。 - Pankaj Nikam
你能提供一个输出样例吗?是一个二维数组吗? - adiga
3个回答

12
你可以为每个由这3个键组成的唯一组合创建一个累加器对象,这些键之间用 - 分隔。然后基于这个新的键使用 reduce 合并数组。使用解构赋值将你需要在PickupTimeSlots中分离的键放入rest变量中。然后使用Object.values获取最终数组:

const slots=[{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T06:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T05:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":0,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToCustomer","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":3,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":3,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":4,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":4,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":5,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T16:22:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":5,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:23:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":6,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":6,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T06:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":1,"ShippingCarrierId":1,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T05:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":0,"PickupTime":"1970-01-01T11:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T00:00:00.000Z","TimeEnd":"1970-01-01T15:59:00.000Z","PickupTimeSlot":"PM","DaysToAdd":0,"PickupTime":"1970-01-01T17:00:00.000Z"},{"WarehouseId":2,"ShippingCarrierId":2,"PostalCodeType":"ShipToDS","TimeStart":"1970-01-01T16:00:00.000Z","TimeEnd":"1970-01-01T23:59:00.000Z","PickupTimeSlot":"AM","DaysToAdd":1,"PickupTime":"1970-01-01T11:00:00.000Z"}]

const merged = slots.reduce((r, { WarehouseId, ShippingCarrierId, PostalCodeType,...rest }) => {
  const key = `${WarehouseId}-${ShippingCarrierId}-${PostalCodeType}`;
  r[key] = r[key] || { WarehouseId, ShippingCarrierId, PostalCodeType, PickupTimeSlots: [] };
  r[key]["PickupTimeSlots"].push(rest)
  return r;
}, {})

const timeTable = Object.values(merged)
console.log(timeTable)


1
您可以使用 Lodash 的 groupBy 函数 - https://lodash.com/docs/4.17.11#groupBy
let groupBy = _.groupBy(array, 'WarehouseId');

给你 ->
wareHouseId1: [...], 
wareHouseId2: [...]

图书馆不支持多级分组。


0
你可以使用reduce来解决这个问题。

let groupBy = function(array, key) {
  return array.reduce(function(result, item) {
    (result[item[key]] = result[item[key]] || []).push(item);
    return result;
  }, {});
};

console.log(groupBy(yourarray, 'yourkey'));


2
密钥可以拥有多个属性吗? - Pankaj Nikam
根据给出的答案,只有一个键可能能够添加。 - Mohamed Raza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接