1

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

1
  • 1
    Loop through the two arrays and turn it into something like {"January": [45.6, 0.5], "March": [59.3, 46.55, 2.21], ...}. Then it will be easy to calculate the averages of each. Commented Dec 9, 2022 at 16:57

3 Answers 3

1

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: []});
Sign up to request clarification or add additional context in comments.

Comments

0

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

1 Comment

Bdobry, huge thanks, also to @chribjel for both of your prompt answers. Both solutions give the intended result .
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.