Javascript 减少对象数组并将其分组

Javascript 减少对象数组并将其分组,javascript,arrays,object,reduce,Javascript,Arrays,Object,Reduce,这是我的对象数组。我正在google sheets中编写一个自定义脚本,以接收交易数据,并将其分解为一个独特的项目列表,在该列表中,订购的金额相加,以创建一个更易于阅读的购买历史记录 products = [ { id: 1, item: 'Beef', category: 'Meat', orderAmount: 5, caseSize: 1, unit: 'Lb', price:

这是我的对象数组。我正在google sheets中编写一个自定义脚本,以接收交易数据,并将其分解为一个独特的项目列表,在该列表中,订购的金额相加,以创建一个更易于阅读的购买历史记录

 products = [ 
      { id: 1,
        item: 'Beef',
        category: 'Meat',
        orderAmount: 5,
        caseSize: 1,
        unit: 'Lb',
        price: 50,
        supplier: 'Sysco' },
      { id: 2,
        item: 'Chicken',
        category: 'Meat',
        orderAmount: 10,
        caseSize: 2,
        unit: 'Grams',
        price: 100,
        supplier: 'Findlay' },
      { id: 3,
        item: 'Fish',
        category: 'Seafood',
        orderAmount: 15,
        caseSize: 3,
        unit: 'Lb',
        price: 40,
        supplier: 'Deodato' },
      { id: 1,    // This is an example duplicate entry
        item: 'Beef',
        category: undefined,
        orderAmount: 100,
        caseSize: 1,
        unit: 'Lb',
        price: 50,
        supplier: 'Sysco' } 
    ]
我有点困惑于如何将其分解为另一个类似这样的对象,其中重复项被删除,但重复项的订单量被相加

uniqueProducts = [ 
  { id: 1,
    item: 'Beef',
    category: 'Meat',
    orderAmount: 105, //this is the altered amount
    caseSize: 1,
    unit: 'Lb',
    price: 50,
    supplier: 'Sysco' },
  { id: 2,
    item: 'Chicken',
    category: 'Meat',
    orderAmount: 10,
    caseSize: 2,
    unit: 'Grams',
    price: 100,
    supplier: 'Findlay' },
  { id: 3,
    item: 'Fish',
    category: 'Seafood',
    orderAmount: 15,
    caseSize: 3,
    unit: 'Lb',
    price: 40,
    supplier: 'Deodato' }
]

我一直在阅读map和reduce函数的使用方法,但我很难弄清楚如何使用如此大的对象来实现它们。

您可以编写一个通用的
函数,该函数使用一个
分组
函数来指定是什么使项目重复,以及
update
函数,用于指定在发现重复项时如何更新结果-

功能组(输入、分组、更新){
功能减速机(res,项目){
常量uniq=石斑鱼(项目)
返回资源(uniq)
?res.set(uniq,更新(res.get(uniq),项目))
:res.set(uniq,项目)
}
返回数组.from(input.reduce(reducer,new Map).values())
}
常数乘积=
[{id:1,项目:'Beef',类别:'Meat',订单数量:5,数量:1,单位:'Lb',价格:50,供应商:'Sysco',{id:2,项目:'Chicken',类别:'Meat',订单数量:10,数量:2,单位:'Grams',价格:100,供应商:'Findlay',{id:3,项目:'Fish',类别:'Seafood',订单数量:15,数量:3,数量:3,单位:'Lb',价格:40,供应商:'Deodato'},{id:1,项目:'Beef',类别:未定义,订单金额:100,大小:1,单位:'Lb',价格:50,供应商:'Sysco'}]
常数结果=
组
(产品)
,item=>item.id
,(原件、副本)=>
({…原始,orderAmount:original.orderAmount+duplicate.orderAmount})
)
console.log(结果)

.as console wrapper{min height:100%;}
有更快的方法可以做到这一点,但一个好的起点是循环搜索匹配结果,如果该项不在列表中,则追加该项。请确保复制该对象,否则将更改原始值

uniqueProducts  = products.reduce((result,item)=> {

   var hit = 0;
   for(var idx=0; idx<result.length; idx++) {
      if (result[idx].id == item.id) {
          hit += 1;
          result[idx].orderAmount += item.orderAmount;
          idx = result.length;
      }
   }

   if (hit === 0) {
       result.push(Object.assign({},item));
   }
   return result;

},[]);
uniqueProducts=products.reduce((结果,项目)=>{
var-hit=0;

对于(var idx=0;idx您可以将元素减少为
映射
并累积
订单金额

const products=[{id:1,项目:'牛肉',类别:'肉',订单数量:5,箱子大小:1,单位:'Lb',价格:50,供应商:'Sysco'},{id:2,项目:'鸡肉',类别:'肉',订单数量:10,箱子大小:2,单位:'g',价格:100,供应商:'Findlay'},{id:3,项目:'Fish',类别:'Seafood',订单数量:15,箱子大小:3,单位:'Lb',价格:40,供应商:'Deodato',{id:1,项目:'Beef',类别:未定义,订单数量:100,箱子大小:1,单位:'Lb',价格:50,供应商:'Sysco'}]
const reducedProductsMap=产品。reduce((map,p)=>{
const previousOrderAmount=map.get(p.id)!==未定义?map.get(p.id)。orderAmount:0
设newP={…p}
newP.orderAmount+=以前的orderAmount
map.set(newP.id,newP)
返回图
},新地图());

console.log(Array.from(reducedProductsMap.values()))
Hi,请分享您尝试过的内容?为什么对象的大小是个问题?您可以在一个较小的对象上仅使用id和orderAmount进行合并吗?当同一属性的值不同时,合并的规则是什么。就像在您的示例中,合并对象的
类别
值存在差异…啊,我的阿波罗gies,第四个被认为是复制品的对象应该将其类别定义为“肉”还有。如果ID匹配,除了orderAmount之外,所有其他属性都应该是相同的。谢谢你的回复!我喜欢它的浓缩程度,但我对一些较新的语法有点不熟悉。你的代码片段的第四行说的是什么?@Nice Turnip`e.orderAmount+=map.get(e.ID)!==undefined?map.get(e.ID).orderAmount:0'正在获取映射中产品的累计
orderAmount
,并将其添加到当前元素'
orderAmount
,当然它可能不存在于映射中,因此我在这种情况下添加0我不确定这是否符合预期,但此方法改变了原始数组。@BenStephens太棒了!我现在修复了它,谢谢