stone rock
stone rock

Reputation: 1953

How to use reduce() in ES6 for calculating average?

I am trying to extract econ and season from JSON data (see screenshot below). I want to find average economy rate per season

eg: season = 2018 economy rate = 10,20,30 so avg economy rate = (10+20+30)/3 = 20

season = 2017 economy rate = 30,40,50 so avg economy rate = (30+40+50)/3 = 40

So I want to calculate sum of all the economy rate for particular season and then take the average i.e divide the total sum for particular season by number of matches in that season.

Below is the code where I am trying to make use of reduce() in ES6:

const economy = bowldata.reduce( (a,{season, econ})  => {
                    a[season] = a[season] + parseInt(econ);
                    return a; 
                }, {});
console.log(economy);

I am getting 2018:NaN but instead I want my output to be 2018:22 , 2017: 50, etc. i.e I want key value pairs of season and average economy rate for that season.

Screenshot:

enter image description here

Let's say I have JSON data:

var bowldata = [
    {
        season:2018
        economy:10
    },
    {   season:2018
        economy:20
    },
    {   season:2018
        economy:30
    },
    {   season:2017
        economy:40
    },
    {   season:2017
        economy:50
    },
    {   season:2016
        economy:10
    },
]

Now the object which reduce() should return is key value pairs of year and average economy rate.

Result: [ 2018:20 , 2017:45 , 2016:10 ]

Upvotes: 2

Views: 1412

Answers (5)

godpanrupesh
godpanrupesh

Reputation: 45

     Hi you can solve the problem by following chain of reduce and map:   
 i) Reduce to season and economies aggregation   
 ii) Map to get season and avg economy   
 iii)Map to get the season and economy  key value string   

bowldata.reduce((acc,b)=>{ const y =acc.find(x => x.s ===b.s); y? y.e.push(b.e) :acc.push({s:b.s, e:[b.e]}); return acc },[])
.map(x => ({s:x.s,e:x.e.reduce((acc,b,i)=> (acc*i + parseInt(b))/(i+1),0)})
)
.map( x=> (x.s +':' + x.e))

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386746

You could take an object as default value for any seasons, becaus you want to calculate the average. For this, you need the count as well.

var bowldata = [{ season: 2001, econ: '30' }, { season: 2001, econ: '40' }, { season: 2001, econ: '50' }, { season: 2001, econ: '60' }, { season: 2002, econ: '30' }, { season: 2002, econ: '40' }, { season: 2002, econ: '50' }, { season: 2003, econ: '60' }, { season: 2003, econ: '30' }, { season: 2003, econ: '40' }, { season: 2003, econ: '50' }, { season: 2003, econ: '60' }],
    economy = bowldata.reduce((a, { season, econ }) => {
        a[season] = a[season] || { sum: 0, count: 0 };
        a[season].sum += +econ;
        a[season].average = a[season].sum / ++a[season].count;
        return a;
    }, Object.create(null)),
    nice = Object.assign(...Object
        .entries(economy)
        .map(([k, { average }]) => ({ [k]: average }))
    );

console.log(nice);
console.log(economy);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Lionel Rowe
Lionel Rowe

Reputation: 5926

To calculate averages rather than totals, you're probably best served with a two-step process, something like this:

const totals = bowldata.reduce((acc, cur)  => {

  if (!acc[cur.season]) {
    acc[cur.season] = {count: 0, total: 0};
  }

  acc[cur.season].count++;
  acc[cur.season].total += parseInt(cur.econ);

  return acc; 
}, {});

const averages = {};

Object.keys(totals).forEach(key => {

  averages[key] = totals[key].total / totals[key].count;

});

Upvotes: 1

Sergio Mazzoleni
Sergio Mazzoleni

Reputation: 1608

the first time you execute a[season] = a[season] + parseInt(econ);, a[season] is not defined. Just initialize it with 0 the fist time you access it.

const economy = bowldata.reduce( (a,{season, econ})  => {
    if (!a[season]) {
        a[season] = 0;
    }
    a[season] = a[season] + parseInt(econ);
    return a; 
}, {});

Upvotes: 1

charlietfl
charlietfl

Reputation: 171690

Change

a[season] = a[season] + parseInt(econ);

To

a[season] = (a[season] || 0 ) + parseInt(econ);

This will account for first instance not having set that property yet so when it is undefined you will be adding the new value to zero.

Upvotes: 2

Related Questions