JS (ES6): Reduce array based on object attribute

青春壹個敷衍的年華 提交于 2019-12-11 08:45:55

问题


I have an array like this:

const fruits = [ 
    { fruit: 'apple',  year: 2018 },
    { fruit: 'apple',  year: 2018 },
    { fruit: 'banana', year: 2018 },
    { fruit: 'orange', year: 2018 },
    { fruit: 'apple',  year: 2017 },
    { fruit: 'apple',  year: 2016 }
];

Now I want to reduce this array to see how many fruits there are each year and how much the total is. So that the result looks like this:

const result = [ 
    { year: 2018, apple: 2, banana: 1, orange: 1 total: 4 },
    { year: 2017, apple: 1, total: 1 },
    { year: 2016, apple: 1, total: 1 }
];

I have tried with reduce, but I couldn't figure out how to group it based on the year. Maybe there is also a lodash helper?


回答1:


Use Object.values and reduce

var output = Object.values(fruits.reduce( (a,c) => {
  a[c.year] = a[c.year] || { year : c.year };  
  a[c.year]["total"] = (a[c.year]["total"] || 0) + 1;
  a[c.year][c.fruit] = (a[c.year][c.fruit] || 0) + 1;
  return a;
},{}));

Demo

var fruits = [{
    fruit: 'apple',
    year: 2018
  },
  {
    fruit: 'apple',
    year: 2018
  },
  {
    fruit: 'banana',
    year: 2018
  },
  {
    fruit: 'orange',
    year: 2018
  },
  {
    fruit: 'apple',
    year: 2017
  },
  {
    fruit: 'apple',
    year: 2016
  }
];

var output = Object.values(fruits.reduce((a, c) => {
  a[c.year] = a[c.year] || {
    year: c.year
  };
  a[c.year]["total"] = (a[c.year]["total"] || 0) + 1;
  a[c.year][c.fruit] = (a[c.year][c.fruit] || 0) + 1;
  return a;
}, {}));

console.log(output);



回答2:


You can use array#reduce to group your data based on year and count the fruit occurrence in an object accumulator. Then get all the values from this object using Object.values()

const fruits = [ { fruit: 'apple', year: 2018 }, { fruit: 'apple', year: 2018 }, { fruit: 'banana', year: 2018 }, { fruit: 'orange', year: 2018 }, { fruit: 'apple', year: 2017 }, { fruit: 'apple', year: 2016 } ],
    result = Object.values(fruits.reduce((r,{fruit, year}) => {
      r[year] = r[year] || {year};
      r[year][fruit] = (r[year][fruit] || 0) + 1;
      r[year]['total'] = (r[year]['total'] || 0) + 1;
      return r;
    },{}));
console.log(result);



回答3:


You could use an array as result set, which keeps the given order of the year.

var fruits = [{ fruit: 'apple',  year: 2018 }, { fruit: 'apple',  year: 2018 }, { fruit: 'banana', year: 2018 }, { fruit: 'orange', year: 2018 }, { fruit: 'apple',  year: 2017 }, { fruit: 'apple',  year: 2016 }],
    result = fruits.reduce((r, { year, fruit }) => {
        var item = r.find(o => o.year === year);
        if (!item) {
            r.push(item = { year });
        }
        item[fruit] = (item[fruit] || 0) + 1;
        return r;
    }, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


来源:https://stackoverflow.com/questions/49918337/js-es6-reduce-array-based-on-object-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!