【问题标题】:Group objects by multiple properties including nested properties and sump up their values按多个属性(包括嵌套属性)对对象进行分组并汇总它们的值
【发布时间】:2020-08-11 16:21:01
【问题描述】:

类似于Group objects by multiple properties in array then sum up their values ,但具有嵌套元素且更复杂。我已经挣扎了好几个小时了。

我有一系列产品:

产品看起来像这样:

{
    "commissioningDate": "2019-09-27",
    "_product": {
        "_id": "aaa",
        "name": "Installation"
    },
    "zones": [
        {
            "_zone": {
                "_id": "KK",
                "name": "Zone kk"
            },
            "category": "category1",
            "zone_quantity": 6
        }
    ],
    "product_quantity": 3
}

预期行为

我做了这个gist,因为示例太长了。

问题

所以我有一系列产品。

1) 仅当 commissioningDate_product._id 相同时,此数组中的产品才被视为重复产品

2) 如果多个产品合并为一个产品:

  • 我们需要一个总结product_quantity
  • 如果可能,我们需要合并产品内的区域数组,否则将其添加到数组中

3) 仅当 _zone._idcategory 相同时,此数组中合并产品的区域才被视为​​重复

4) 如果许多区域被合并到一个区域中,我们需要一个总结zone_quantity

【问题讨论】:

    标签: javascript arrays duplicates


    【解决方案1】:

    假设您的单个产品区域的长度始终为 1。

    const sample = [
        {
            "commissioningDate": "2019-09-27",
            "_product": {
                "_id": "aaa",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "KK",
                        "name": "Zone kk"
                    },
                    "category": "category1",
                    "zone_quantity": 6
                }
            ],
            "product_quantity": 3
        },
        {
            "commissioningDate": "2019-09-27",
            "_product": {
                "_id": "aaa",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "KK",
                        "name": "Zone kk"
                    },
                    "category": "category2",
                    "zone_quantity": 3
                }
            ],
            "product_quantity": 2
        },
        {
            "commissioningDate": "2019-09-27",
            "_product": {
                "_id": "aaa",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "KK",
                        "name": "Zone kk"
                    },
                    "category": "category2",
                    "zone_quantity": 4
                }
            ],
            "product_quantity": 5
        },
        {
            "commissioningDate": "2019-09-27",
            "_product": {
                "_id": "aaa",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "CC",
                        "name": "Zone cc"
                    },
                    "category": "category2",
                    "zone_quantity": 6
                }
            ],
            "product_quantity": 1
        },
        {
            "commissioningDate": "2019-09-27",
            "_product": {
                "_id": "bbbb",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "CC",
                        "name": "Zone cc"
                    },
                    "category": "category2",
                    "zone_quantity": 8
                }
            ],
            "product_quantity": 2
        },
        {
            "commissioningDate": "2019-09-26",
            "_product": {
                "_id": "bbbb",
                "name": "Installation"
            },
            "zones": [
                {
                    "_zone": {
                        "_id": "CC",
                        "name": "Zone cc"
                    },
                    "category": "category2",
                    "zone_quantity": 8
                }
            ],
            "product_quantity": 2
        }
    ]
    
    //reduce initialze value is an empty object
    const res = sample.reduce((group, item) => {
      //for each item, generate a key k by combining item commissioningDate and item _product._id seperated //by a comma 
      const k = `${item.commissioningDate},${item._product._id}`;
      
      //check if this key k exists in our object group(which is an empty object when we check the first //item)
      //if it is not in the object, we save the key k and its value which is current item into the object //group
      if(!group[k]) group[k] = Object.assign({}, item);
      
      //if it is in the object already 
      else{
      
      //we sum up current item quantity to the group of this item
        group[k].product_quantity+=item.product_quantity;
        
        //find index of zone in current group zones has the same zone id and category as item's
        for(const itemZone of item.zones){
          const zoneIdx = group[k].zones.findIndex(zone => zone._zone._id === itemZone._zone._id && zone.category === itemZone.category)
    
          //index is -1, it's not in group zones, we push the zone to group zones array
          if(zoneIdx === -1){
            group[k].zones.push(itemZone)
          }
          //in group zones, we sum up zone_quantity
          else{
            group[k].zones[zoneIdx].zone_quantity += itemZone.zone_quantity
          }
        }
        
      }
      //update current group
      return group
    }, {})
    
    //recall keys are our custom identifier for different groups of items, values are actually groups of //items, so we only need to get values from group object
    console.log(Object.values(res))

    【讨论】:

    • 谢谢,我要测试一下并试着理解它。但大多数时候我的单个产品区域的长度超过 1
    • @AmineDa。你也可以添加这样的例子吗?
    • 如果你的 zone 长度大于 1,它会很相似,只需迭代 items zone 并与当前 group zone 进行比较。
    • @Colin 您唯一需要更改的是findIndexgroup[k].zones.push(item.zones[0]) 这部分,以防有多个您需要使用filter 然后检查长度是否找到它
    • @AmineDa。您可以使用 object.assign 来复制对象,无需使用传播。我认为 object.assign 应该可以用 es5
    猜你喜欢
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2015-05-04
    • 2023-01-06
    • 2018-07-02
    • 1970-01-01
    相关资源
    最近更新 更多