![](/img/trans.png)
[英]how to add object in nested array of objects without mutating original source
[英]algorithm to add up objects in an array without mutating the original array
我有一系列待处理的付款作为对象,我想知道同一家商店的所有付款的总和。 一旦函数正确计算就调用该函数,当我再次调用该函数时,它将使对象的原始数组发生变化。 我不明白为什么要在其上进行映射时对其进行突变。
我需要该功能不使对象的原始数组发生变异。 它应该进行计算,只是给我结果。 如果再次调用,则也不会将当前总和相加。 它应该从头开始。
let pending = [
{Date: "20/12/2018",
Company:[
{Name: "Asda", Amount: 5.5},
{Name: "M&S", Amount: 10},
{Name: "Nisa", Amount: 15},
{Name: "Iceland", Amount: 10},
{Name: "Tesco", Amount: 5}
]},
{Date: "20/12/2018",
Company:[
{Name: "Asda", Amount: 5.5},
{Name: "M&S", Amount: 10},
{Name: "Nisa", Amount: 15},
{Name: "Iceland", Amount: 10},
{Name: "Tesco", Amount: 5}
]},
{Date: "20/12/2018",
Company:[
{Name: "Asda", Amount: 5.5},
{Name: "M&S", Amount: 10},
{Name: "Nisa", Amount: 15},
{Name: "Iceland", Amount: 10},
{Name: "Tesco", Amount: 5}
]},
{Date: "20/12/2018",
Company:[
{Name: "Asda", Amount: 5.5},
{Name: "M&S", Amount: 10},
{Name: "Nisa", Amount: 15},
{Name: "Iceland", Amount: 10},
{Name: "Tesco", Amount: 5}
]}
]
function returnSpendTotals() {
let sumSpend = []
let spendArray = pending.map(activities => activities.Company)
spendArray.flat().forEach(spend => {
let shopName = sumSpend.find(item => item.Name === spend.Name)
if (shopName) {
shopName.Amount += spend.Amount
} else {
sumSpend.push(spend)
}
})
return sumSpend
}
它应该在每次我调用returnSpendTotals()时返回
[{Name: "Asda", Amount: 22},
{Name: "M&S", Amount: 40},
{Name: "Nisa", Amount: 60},
{Name: "Iceland", Amount: 40},
{Name: "Tesco", Amount: 20}]
但是如果我第二次打电话给我,这就是我得到的
[{Name: "Asda", Amount: 38.5},
{Name: "M&S", Amount: 70},
{Name: "Nisa", Amount: 105},
{Name: "Iceland", Amount: 70},
{Name: "Tesco", Amount: 35}]
现在有待处理的第一个对象
{Company: [
{Name: "Asda", Amount: 38.5},
{Name: "M&S", Amount: 70},
{Name: "Nisa", Amount: 105},
{Name: "Iceland", Amount: 70},
{Name: "Tesco", Amount: 35}],
Date: "20/12/2018"}
其余待处理的对象保持不变
当您找到一家商店时:
let shopName = sumSpend.find(item => item.Name === spend.Name)
您可以获得对数据结构中的对象的引用 。 然后,您的代码修改该对象:
shopName.Amount += spend.Amount
我不确定确切的建议是解决方案,因为尚不清楚您要做什么。 可能您应该保持单独的运行总计,而不是更改“ shop”对象。
还要注意, .map()
进程在您的函数的早期:
let spendArray = pending.map(activities => activities.Company)
同样会产生一个列表,该列表由返回原始数据结构的引用组成。
使用此解决方案,它很简单,有效,没有任何幻想,只需创建一个对象,为该对象分配属性,然后遍历数据对象即可。
const data=[{Date:"20/12/2018",Company:[{Name:"Asda",Amount:5.5},{Name:"M&S",Amount:10},{Name:"Nisa",Amount:15},{Name:"Iceland",Amount:10},{Name:"Tesco",Amount:5}]},{Date:"20/12/2018",Company:[{Name:"Asda",Amount:5.5},{Name:"M&S",Amount:10},{Name:"Nisa",Amount:15},{Name:"Iceland",Amount:10},{Name:"Tesco",Amount:5}]},{Date:"20/12/2018",Company:[{Name:"Asda",Amount:5.5},{Name:"M&S",Amount:10},{Name:"Nisa",Amount:15},{Name:"Iceland",Amount:10},{Name:"Tesco",Amount:5}]},{Date:"20/12/2018",Company:[{Name:"Asda",Amount:5.5},{Name:"M&S",Amount:10},{Name:"Nisa",Amount:15},{Name:"Iceland",Amount:10},{Name:"Tesco",Amount:5}]}]; const companies = {}; data.forEach(obj => obj.Company.forEach(o => { companies[o.Name] = companies[o.Name] == null ? 0 : companies[o.Name]; companies[o.Name] += o.Amount; })); console.log(companies);
这很相似,只是花哨了一点……这是受到Nina Scholz的回答的启发,我是语法的爱好者。
const pending = [{ Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }]; const compelte = pending.reduce((r, { Company }) => { Company.forEach(({ Name, Amount }) => r[Name] == null ? r[Name] = 0 : r[Name] += Amount); return r; }, {}); console.log(compelte);
您可以采用已分解的属性,并为结果集构建一个新对象,以防止相同的对象引用所使用的数据。
function returnSpendTotals() { return pending.reduce((r, { Company }) => { Company.forEach(({ Name, Amount }) => { let shop = r.find(item => item.Name === Name) if (shop) { shop.Amount += Amount; } else { r.push({ Name, Amount }); } }); return r; }, []); } let pending = [{ Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }, { Date: "20/12/2018", Company: [{ Name: "Asda", Amount: 5.5 }, { Name: "M&S", Amount: 10 }, { Name: "Nisa", Amount: 15 }, { Name: "Iceland", Amount: 10 }, { Name: "Tesco", Amount: 5 }] }]; console.log(returnSpendTotals());
function returnSpendTotals() {
let companies = {}
pending.forEach(item => {
item.Company.forEach(company => {
if (!companies[company.Name]) {
companies[company.Name] = company.Amount;
} else {
companies[company.Name] += company.Amount;
}
})
})
return companies
}
returnSpendTotals(pending)
// result: {Asda: 22, M&S: 40, Nisa: 60, Iceland: 40, Tesco: 20}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.