2

I am trying to calculate the average of values with the same key in a array of objects. Not all the Objects consist of the same values as the other but I still want the average returned depending on how many times it appears in the array. For example I want

const Object1 = [{
  2005: 5.6,
  2006: 5.2
}, {
  2005: 5.6,
  2006: 5.7,
  2007: 5.4
}, {
  2005: 5.6,
  2006: 5.9,
  2007: 5.8
}]

To return

{
  2005: 5.599999999999999,
  2006: 5.6000000000000005,
  2007: 5.6
}

This is what I have tried so far. Right now the problem is that I have no way to / it by the amount of times it appears. And if it is missing the year the value becomes undefined and this causes the result to be NaN.

const Object1 = [{
  2005: 5.6,
  2006: 5.2
}, {
  2005: 5.6,
  2006: 5.7,
  2007: 5.4
}, {
  2005: 5.6,
  2006: 5.9,
  2007: 5.8
}]
const years = Object.keys(Object.assign({}, ...Object1));
const Result = years.reduce((a, v) => ({
  ...a,
  [v]: v
}), {})
console.log(Result)
years.map((year) => {

  const value =
    Object1.map(function(obj) {
      return obj[year]
    }).reduce(function(a, b) {
      return (a + b)
    }) / years.length
  Result[year] = value
})
console.log(Result)

3 Answers 3

2

You could group points by year and calculate points solely based on each group

const object1 = [
  {
    2005: 5.6,
    2006: 5.2,
  },
  {
    2005: 5.6,
    2006: 5.7,
    2007: 5.4,
  },
  {
    2005: 5.6,
    2006: 5.9,
    2007: 5.8,
  },
];

const groupPointByYears = object1.reduce((map, obj) => {
  for (const [year, point] of Object.entries(obj)) {
    if (!map.has(year)) {
      map.set(year, []);
    }
    map.get(year).push(point);
  }

  return map;
}, new Map());

console.log(Array.from(groupPointByYears));

const res = Object.fromEntries(
  Array.from(groupPointByYears).map(([year, points]) => [
    year,
    points.reduce((sum, point) => sum + point, 0) / points.length,
  ])
);

console.log(res);

Sign up to request clarification or add additional context in comments.

1 Comment

Out of the 3 suggestions I have gotten you think this is the best one? @hgb123
2
const years = Object1.reduce(( prev, curr ) => {
    for (const key in curr) prev[key] = (prev[key] || []).concat(curr[key])
    return prev
}, {})

const Result = {}
for (const year in years) {
    Result[year] = years[year].reduce(( prev, val ) => prev + val, 0) / years[year].length
}

console.log(Result)

this code first puts all values of every year in an array in an object (that's what the first reduce does) then it loops over every year and adds the average (sum of all values divided by the amount of values) to the Result object

3 Comments

I like this answer alot, However lets say I were to add one more nested Object and than put the years into that. Like this const Object1 = [{ Male: { 2005: 5.6, 2006: 5.2, }, Female: { 2005: 5.6, 2006: 5.4, } }, { Male: { 2005: 5.9, 2006: 5.2, 2007: 5.3 }, Female: { 2005: 5.6, 2006: 5.4, 2007: 5.9, } }, { Male: { 2005: 5.9, 2006: 5.2, 2007: 5.3 }, Female: { 2005: 5.2, 2006: 5.9, 2007: 5.1, } } ];
How Would i make that return {Male:{2017:5.55, etcc.}, Female:{2017...}}
well you would have to loop over the object, like i did in the first one, to group them by "male" and "female" and then loop over "male" and "female" and just do exactly what i did. that is almost an entirely new question, do you still need me to edit my answer to include a code snippet to solve this or have you figured out a way?
2

I made some changes based on your code

const Object1 = [{
  2005: 5.6,
  2006: 5.2
}, {
  2005: 5.6,
  2006: 5.7,
  2007: 5.4
}, {
  2005: 5.6,
  2006: 5.9,
  2007: 5.8
}]
const years = Object.keys(Object.assign({}, ...Object1));
const Result = years.reduce((a, v) => ({
  ...a,
  [v]: v
}), {})
console.log(Result)
years.map((year) => {
 // Filter out keywords while removing undefined ones
  var filteredYear = Object1.map(function(obj) {
      return obj[year]
    }).filter(e=>e!=undefined)
 // Perform a reduce calculation with the filtered results
  const value =
  filteredYear.reduce(function(a, b) {
      return (a + b)
    }) / filteredYear.length
  Result[year] = value
})
console.log(Result)

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

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.