Javascript 减少对象数组并将其分组
这是我的对象数组。我正在google sheets中编写一个自定义脚本,以接收交易数据,并将其分解为一个独特的项目列表,在该列表中,订购的金额相加,以创建一个更易于阅读的购买历史记录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:
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太棒了!我现在修复了它,谢谢