Home > front end >  Calculate average of array of objects with filtering for undefined
Calculate average of array of objects with filtering for undefined

Time:04-21

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)

CodePudding user response:

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

CodePudding user response:

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

CodePudding user response:

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)

  • Related