减少和求和对象条目的数组

3

从下面的数组开始:

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

我需要将这个表格按照每年一行的方式进行转换,其中每个“Title”的数值都应该有一个对应的“Sum”值,并且预算值应该被汇总在一起,例如:

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

我的平台不支持ES6,通过之前的帖子中的答案,我已经使用.reduce来实现大部分功能:

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

但我找不到一种方法来将预算数字相加,并将其添加到同一条目中。我怀疑需要在重复的数组上执行单独的reduce函数,并使用Year作为键,使用forEach循环将结果推入res数组中。有人能看到在同一个reduce函数中完成这个任务的方法吗?
1个回答

3
reduce回调函数中初始化一个年份对象时,还要将Budget属性初始化为0。然后,在该年份的每次迭代中,除了设置Sample属性之外,还需加上Budget属性的值。

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和polyfill,使您能够使用最新版本的语言编写代码,同时保持对过时浏览器的兼容性,这种情况下,代码可以变得更加美观:

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


使用shimmed ES6,甚至可以使用Object.values(arr.reduce((a, { Year, Title, Sum, Budget }) => ({...a, [Year] : {...(a[Year] || {}), Year, [Title]: Sum, Budget: (a[Year] || {Budget: 0}).Budget + Budget}}), {})) - Scott Sauyet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接