在不改变原始数组的情况下在数组中添加对象的算法

时间:2018-12-20 16:30:27

标签: javascript algorithm dictionary

我有一系列待处理的付款作为对象,我想知道同一家商店的所有付款的总和。一旦函数正确计算就调用该函数,当我再次调用该函数时,它将使对象的原始数组发生变化。 我不明白为什么要在其上进行映射时对其进行突变。

我需要不改变对象原始数组的功能。它应该进行计算,只是给我结果。如果再次调用,则也不会将当前总和相加。它应该从头开始。

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"}

其余待处理的对象保持不变

4 个答案:

答案 0 :(得分:1)

找到商店时:

let shopName = sumSpend.find(item => item.Name === spend.Name)

您获得对属于数据结构一部分的对象的引用。然后,您的代码将修改该对象:

      shopName.Amount += spend.Amount

我不确定确切的建议是什么,因为尚不清楚您要做什么。可能您应该保持单独的运行总计,而不是更改“ shop”对象。

还要注意,您的函数中的.map()进程较早:

let spendArray = pending.map(activities => activities.Company)

同样会产生一个列表,该列表由对原始数据结构的引用组成。

答案 1 :(得分:1)

使用此解决方案,它很简单,有效,没有任何幻想,只需创建一个对象,为该对象分配属性,然后遍历数据对象即可。

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);

答案 2 :(得分:1)

您可以采用已分解的属性,并为结果集构建一个新对象,以防止同一对象引用所使用的数据。

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());

答案 3 :(得分:0)

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}