уменьшить и суммировать массив объектов - PullRequest
3 голосов
/ 04 июня 2019

Из следующего массива:

var arr = [{ "Year": 2019, "Title": "Sample1", "Sum": 1020000.0, "Budget":0}, 
{  "Year": 2019,  "Title": "Sample2",  "Sum": 2546658.0,  "Budget":100},
{  "Year": 2019,  "Title": "Sample3",  "Sum": 1020000.0,  "Budget":1000},
{  "Year": 2020,  "Title": "Sample1",  "Sum": 3472000.0,  "Budget":100}, 
{  "Year": 2020,  "Title": "Sample2",  "Sum": 1020000.0,  "Budget":10},
{  "Year": 2020,  "Title": "Sample3",  "Sum": 2452000.0,  "Budget":50},
{  "Year": 2021,  "Title": "Sample1",  "Sum": 1000.0,  "Budget":100}, 
{  "Year": 2021,  "Title": "Sample2",  "Sum": 119000.0,  "Budget":10},
{  "Year": 2021,  "Title": "Sample3",  "Sum": 234000.0,  "Budget":50}]
]

Мне нужно изменить это на один год в строке, где значение каждого «Заголовка» имеет запись со значением «Сумма», а значения бюджета должны быть агрегированы вместе, т. Е.

[{ "Year": 2019, "Sample1": 1020000.0, "Sample2":2546658.0, "Sample3":1020000.0 , "Budget":1100},{  etc]

Моя платформа не поддерживает ES6, благодаря ответам из предыдущего поста, который я использовал. Для получения большей части пути выполните следующие действия:

var res = arr.reduce(function(acc, curr) {
  acc[curr.Year] = acc[curr.Year];
  acc[curr.Year] = acc[curr.Year] || { Year: curr.Year } ;
  acc[curr.Year][curr.Title] = curr.Sum;
  return acc;

res = Object.keys(res).map(function(key) {
return res[key];
    });

Это производит:

[{ "Year": 2019, "Sample1": 1020000.0, "Sample2":2546658.0, "Sample3":1020000.0 }, 
{ "Year": 2020, "Sample2": 3472000.0, "Sample2":1020000.0, "Sample3":2452000.0}, 
{ "Year": 2021, "Sample3": 1000.0, "Sample2":119000.0, "Sample3":234000.0}]

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

1 Ответ

3 голосов
/ 04 июня 2019

При инициализации объекта Year в обратном вызове reduce также инициализируйте свойство Budget равным 0. Затем на каждой итерации для этого года добавляйте свойство бюджет в дополнение к установке свойства Sample:

var arr = [{ "Year": 2019, "Title": "Sample1", "Sum": 1020000.0, "Budget":0}, 
  {  "Year": 2019,  "Title": "Sample2",  "Sum": 2546658.0,  "Budget":100},
  {  "Year": 2019,  "Title": "Sample3",  "Sum": 1020000.0,  "Budget":1000},
  {  "Year": 2020,  "Title": "Sample1",  "Sum": 3472000.0,  "Budget":100}, 
  {  "Year": 2020,  "Title": "Sample2",  "Sum": 1020000.0,  "Budget":10},
  {  "Year": 2020,  "Title": "Sample3",  "Sum": 2452000.0,  "Budget":50},
  {  "Year": 2021,  "Title": "Sample1",  "Sum": 1000.0,  "Budget":100}, 
  {  "Year": 2021,  "Title": "Sample2",  "Sum": 119000.0,  "Budget":10},
  {  "Year": 2021,  "Title": "Sample3",  "Sum": 234000.0,  "Budget":50}
]
var res = arr.reduce(function(acc, curr) {
  acc[curr.Year] = acc[curr.Year] || { Year: curr.Year, Budget: 0 } ;
  //                                                    ^^^^^^^^^
  acc[curr.Year][curr.Title] = curr.Sum;
  acc[curr.Year].Budget += curr.Budget;
  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  return acc;
}, {});
var output = Object.keys(res).map(function(key) {
  return res[key];
});
console.log(output);

Обратите внимание, что строка в вашем исходном коде

acc[curr.Year] = acc[curr.Year];

вообще ничего не выполняет - вы можете полностью его опустить.

Вы можете рассмотреть возможность использования Babel и polyfills, что позволит вам писать код на последней и самой лучшей версии языка, сохраняя совместимость для устаревших браузеров, и в этом случае код может быть предварительно преобразован в:

var arr=[{"Year":2019,"Title":"Sample1","Sum":1020000.0,"Budget":0},{"Year":2019,"Title":"Sample2","Sum":2546658.0,"Budget":100},{"Year":2019,"Title":"Sample3","Sum":1020000.0,"Budget":1000},{"Year":2020,"Title":"Sample1","Sum":3472000.0,"Budget":100},{"Year":2020,"Title":"Sample2","Sum":1020000.0,"Budget":10},{"Year":2020,"Title":"Sample3","Sum":2452000.0,"Budget":50},{"Year":2021,"Title":"Sample1","Sum":1000.0,"Budget":100},{"Year":2021,"Title":"Sample2","Sum":119000.0,"Budget":10},{"Year":2021,"Title":"Sample3","Sum":234000.0,"Budget":50}]

const output = Object.values(arr.reduce((a, { Year, Title, Sum, Budget }) => {
  a[Year] = a[Year] || { Year, Budget: 0 };
  a[Year][Title] = Sum;
  a[Year].Budget += Budget;
  return a;
}, {}));
console.log(output);
...