Группируйте объекты по нескольким свойствам, включая вложенные свойства, и суммируйте их значения - PullRequest
1 голос
/ 28 апреля 2020

это похоже на Группировать объекты по нескольким свойствам в массиве, затем суммировать их значения , но с вложенными элементами и более сложными. Я боролся в течение нескольких часов.

У меня есть множество продуктов:

продукт выглядит так:

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

Ожидаемое поведение

Я сделал это гист потому что пример слишком длинный.

Задача

Итак, у меня есть множество продуктов.

1) продукты в этом массиве считаются дубликатами, только если их commissioningDate и _product._id одинаковы

2), если многие продукты объединены в один продукт:

  • нам нужен a для суммирования product_quantity
  • , нам нужно объединить массив зон внутри продукта, если это возможно, иначе добавить его в массив

3) зоны объединенного продукта в этом массиве считаются дубликатами только в том случае, если их _zone._id и category являются одинаковыми

4) если много зон объединено в одну зону, нам нужно сложить до zone_quantity

1 Ответ

2 голосов
/ 28 апреля 2020

Предположим, что ваши отдельные продуктовые зоны всегда имеют длину 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))
...