如何解决减少和分组对象数组
这是我的对象数组。我正在谷歌表格中编写一个自定义脚本来接收交易数据并将其分解为一个独特项目列表,其中订购的金额相加以创建更易于阅读的购买历史记录。
products = [
{ id: 1,item: 'Beef',category: 'Meat',orderAmount: 5,caseSize: 1,unit: 'Lb',price: 50,supplier: 'Sysco' },{ id: 2,item: 'Chicken',orderAmount: 10,caseSize: 2,unit: 'Grams',price: 100,supplier: 'Findlay' },{ id: 3,item: 'Fish',category: 'Seafood',orderAmount: 15,caseSize: 3,price: 40,supplier: 'Deodato' },{ id: 1,// This is an example duplicate entry
item: 'Beef',category: undefined,orderAmount: 100,supplier: 'Sysco' }
]
我对如何将其分解为另一个对象感到有些困惑,其中删除了重复项,但将重复项的 orderAmounts 相加。
uniqueProducts = [
{ id: 1,orderAmount: 105,//this is the altered amount
caseSize: 1,supplier: 'Deodato' }
]
我一直在阅读如何使用 map 和 reduce 函数,但我很难弄清楚如何使用如此大的对象来实现它们。
解决方法
您可以编写一个通用的 group
函数,该函数采用 grouper
函数来指定使项目重复的原因,并使用 update
函数指定重复项时如何更新结果被发现 -
function group(input,grouper,update) {
function reducer(res,item) {
const uniq = grouper(item)
return res.has(uniq)
? res.set(uniq,update(res.get(uniq),item))
: res.set(uniq,item)
}
return Array.from(input.reduce(reducer,new Map).values())
}
const products =
[{id:1,item:'Beef',category:'Meat',orderAmount:5,caseSize:1,unit:'Lb',price:50,supplier:'Sysco'},{id:2,item:'Chicken',orderAmount:10,caseSize:2,unit:'Grams',price:100,supplier:'Findlay'},{id:3,item:'Fish',category:'Seafood',orderAmount:15,caseSize:3,price:40,supplier:'Deodato'},{id:1,category:undefined,orderAmount:100,supplier:'Sysco'}]
const result =
group
( products,item => item.id,(original,duplicate) =>
({ ...original,orderAmount: original.orderAmount + duplicate.orderAmount })
)
console.log(result)
.as-console-wrapper { min-height: 100%; }
[
{
"id": 1,"item": "Beef","category": "Meat","orderAmount": 105,// <- grouped
"caseSize": 1,"unit": "Lb","price": 50,"supplier": "Sysco"
},{
"id": 2,"item": "Chicken","orderAmount": 10,"caseSize": 2,"unit": "Grams","price": 100,"supplier": "Findlay"
},{
"id": 3,"item": "Fish","category": "Seafood","orderAmount": 15,"caseSize": 3,"price": 40,"supplier": "Deodato"
}
]
上面我们看到 group
期望一个数组作为输入并返回一个数组作为输出。如果 group
接受任何 iterable 并返回一个可迭代对象,我们可以使它更有用。数组是可迭代的,因此它们仍然可以按预期工作,但其他可迭代对象也可以工作 -
function group(input,update) {
const res = new Map
for (const item of input) {
const uniq = grouper(item)
res.set
( uniq,res.has(uniq)
? update(res.get(uniq),item)
: item
)
}
return res.values()
}
function* products () {
yield {id:1,supplier:'Sysco'}
yield {id:2,supplier:'Findlay'}
yield {id:3,supplier:'Deodato'}
yield {id:1,supplier:'Sysco'}
}
const grouping =
group
( products(),orderAmount: original.orderAmount + duplicate.orderAmount })
)
for (const item of grouping)
console.log(item)
注意输出是如何不包裹在数组中的 -
{
"id": 1,// <- grouped
"caseSize": 1,"supplier": "Sysco"
}
{
"id": 2,"supplier": "Findlay"
}
{
"id": 3,"supplier": "Deodato"
}
要从任何可迭代对象中获取数组,可以使用 Array.from
函数 -
Array.from(grouping) // => [ ... ]
,
有更快的方法可以做到这一点,但一个好的起点是遍历匹配结果,如果该项目不在列表中,则附加该项目。请务必复制对象,否则您将更改原始值。
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;
},[]);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。