алгоритм добавления объектов в массив без изменения исходного массива - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть массив ожидающих платежей в качестве объектов, и я хочу знать общую сумму всех платежей вместе, поскольку они предназначены для одних и тех же магазинов.когда функция вызывается один раз, она вычисляет правильно, когда я вызываю ее снова, она мутирует исходный массив объектов.Я не понимаю, почему это мутирует, когда я намечаю это.

Мне нужна функция, чтобы не изменять исходный массив объектов.Нужно сделать расчет и просто дать мне результат.Также он не должен добавлять текущую сумму, если она вызывается снова.Он должен делать это с нуля.

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 голосов
/ 20 декабря 2018
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}
0 голосов
/ 20 декабря 2018

С этим решением все просто, оно работает, ничего особенного не происходит, просто создайте объект, назначьте свойства этому объекту и итерируйте по объекту данных, вот и все.

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

Редактировать

Это очень похоже, только немного более причудливо ... Это вдохновлено ответом от Нины Шольц, я фанатсинтаксис.

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);
0 голосов
/ 20 декабря 2018

Вы можете взять деструктурированные свойства и построить новый объект для набора результатов, чтобы предотвратить ссылку того же объекта на использованные данные.

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());
0 голосов
/ 20 декабря 2018

Когда вы находите магазин:

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

вы получаете ссылку на объект, который является частью вашей структуры данных.Затем ваш код изменяет этот объект:

      shopName.Amount += spend.Amount

Я не совсем уверен, что предложить в качестве исправления, потому что не совсем ясно, что вы пытаетесь сделать.Вероятно, вам следует хранить отдельный промежуточный итог вместо того, чтобы изменять свои объекты "магазина".

Также обратите внимание, что процесс .map() ранее в вашей функции:

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

аналогичным образом приводит ксписок, который состоит из ссылок обратно в исходную структуру данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...