Home > front end >  Aggregate and average values inside an object Javascript
Aggregate and average values inside an object Javascript

Time:12-10

I have an object in the form of:

{
"Dates": ["January", "January", "March", "March", "March", "November", "November"],
"Values": [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5]
}

What I need is to aggregate the values in "Values" (average) by month

The object I am seeking:

{
"Dates":["January", "March", "November"],
"Values":[23.05, 36.02, 27]
}

I know there have been several posts about it here. But I am not sure how to apply it to an object with arrays. Would appreciate very much any ideas. Thanks

CodePudding user response:

Something like this should work.

// First reduce the data to an object with the dates as keys
const grouped = data.Dates.reduce((acc, date, i) => {
  if (acc[date]) {
    acc[date].push(data.Values[i])
  } else {
    acc[date] = [data.Values[i]]
  }
  return acc
}, {});

// Then reduce the object to the desired format
const result = Object.keys(grouped).reduce((acc, date) => {
  acc.Dates.push(date)
  acc.Values.push(grouped[date].reduce((a, b) => a   b) / grouped[date].length)
  return acc
}, {Dates: [], Values: []});

CodePudding user response:

You could try something like this.

const obj = {
  "Dates": ["January", "January", "March", "March", "March", "November", "November"],
  "Values": [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5]
}

// new Set() will remove all duplicated items
const months = [...new Set(obj.Dates)];

const result = {
  "Dates": months,
  "Values": months.map(month => {
    // find values for given month
    const values = obj.Values.filter((_, i) => obj.Dates[i] === month);
    
    // sum the values and divide by the amount
    return values.reduce((a, b) => a   b) / values.length;
  })
}

console.log(result);

CodePudding user response:

You could split the tasks into smaller parts and use functions for

  • grouping,
  • getting an average of an array
  • getting the complete result by taking an object of groups.

const
    getAverage = array => array.reduce((a, b) => a   b) / array.length,
    groupBy = (keys, values) => {
        const groups = {};

        for (let i = 0; i < keys.length; i  )
            (groups[keys[i]] ??= []).push(values[i]);

        return groups;
    },
    getAverages = groups => Object.entries(groups).reduce((r, [month, values]) => {
        r.Dates.push(month);
        r.Values.push(getAverage(values));
        return r;
    }, { Dates: [], Values: [] }),
    data = { Dates: ["January", "January", "March", "March", "March", "November", "November"], Values: [45.6, 0.5, 59.3, 46.56, 2.21, 48.59, 5.5] },
    result = getAverages(groupBy(data.Dates, data.Values));

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

  • Related