0

My brain is melting from this... I'm trying to accomplish the following:

I have an array of objects which have also have arrays:

const data = [
  {
    seatChartResults: {
     '10th': [40, 40, 40, 39, 39, 38, 38, 38, 38, 38],
     '90th': [44, 44, 44, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
  {
    seatChartResults: {
     '10th': [41, 40, 40, 39, 39, 39, 38, 38, 38, 38],
     '90th': [43, 44, 45, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
]

Now I want to achieve something that will get the average of each index of these keys, so for example:

(data[0].seatChartResults['10th'][0] + data[1].seatChartResults['10th'][0]) / 2

and so on ...

The end result is an aggregation of the objects into the same structure:

  { // With all averages aggregated
    seatChartResults: {
     '10th': [41, 40, 40, 39, 39, 39, 38, 38, 38, 38],
     '90th': [43, 44, 45, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },

This is what I have now:

const avgSeatChartResults = (allLambdas) => {

  return allLambdas.reduce((acc, { seatChartResults }) => {

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

      const allKeys = [acc.seatChartResults[key] = seatChartResults[key]]

      allKeys.map(item => item.reduce((acc, currValue) => acc + currValue, 0) / item.length )      

    })

    return acc

  }, { seatChartResults: {} })

}

but... I'm not sure if correctly doing this. Please help.

0

3 Answers 3

1

One approach you can use to do this is to:

  • first compute the sums for corresponding arrays and collect those in a map (or object if you prefer that)
  • then further reduce that to the desired object by computing averages of each entry in each array

const data = [{
    seatChartResults: {
      '10th': [40, 40, 40, 39, 39, 38, 38, 38, 38, 38],
      '90th': [44, 44, 44, 45, 45, 46, 46, 46, 47, 47],
      'avg': [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
  {
    seatChartResults: {
      '10th': [41, 40, 40, 39, 39, 39, 38, 38, 38, 38],
      '90th': [43, 44, 45, 45, 45, 46, 46, 46, 47, 47],
      'avg': [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
];

const res = Array.from(data.reduce((acc, {seatChartResults}) => { // add corrsponding array entries
      Object.entries(seatChartResults).forEach(([k, arr]) => {
        acc.set(k, arr.map((n, i) => ((acc.get(k) || [])[i] || 0) + n));
      });
      return acc;
    }, new Map()).entries())
    .reduce((acc, [k, arr]) => { // compute average
      acc.seatChartResults[k] = arr.map(n => n / data.length);
      return acc;
    }, {seatChartResults: {}});

console.log(res);

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

Comments

1

You are not returning allKeys in your final call.

But anyway even if you do, your implementation will not return what you actually want.

Keep in mind that when using the functional array methods you always need to return.

A working version of your code can be :

/**
 * Return average of array with key `seatChartResults`
 *
 * @param data  The data provided
 */
function average( data ) {
    return {
        seatChartResults : data
            .reduce( ( acc, { seatChartResults }, i, arr ) => (
                Object
                    .keys( seatChartResults )
                    // Each key will replace the reduced accumulator object
                    .reduce( ( acc, key ) => Object.assign( acc, {
                        [key] : seatChartResults[key]
                            // The key will be replaced with the summed arrays
                            // If the accumulated key does not exist it will be
                            // initialized with []. If the accumulated value of the index
                            // in this key does not exist it will be initialized with
                            // 0
                            .map( ( v, i ) => (acc[key] ? (acc[key][i] || 0) : 0) + v )
                            // If it is the last object we divide by the amount of
                            // objects to get the average
                            .map( sum => i === arr.length - 1 ? sum / arr.length : sum )
                    } ), acc ) // <--- Note we use acc as our initial reducer value
            ), {} )
    };
}

const data = [
  {
    seatChartResults: {
     '10th': [40, 40, 40, 39, 39, 38, 38, 38, 38, 38],
     '90th': [44, 44, 44, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
  {
    seatChartResults: {
     '10th': [41, 40, 40, 39, 39, 39, 38, 38, 38, 38],
     '90th': [43, 44, 45, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  }
]

console.log( average( data ) );

Comments

0

You can still achieve the result with loops

const data = [
  {
    seatChartResults: {
     '10th': [40, 40, 40, 39, 39, 38, 38, 38, 38, 38],
     '90th': [44, 44, 44, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
  {
    seatChartResults: {
     '10th': [41, 40, 40, 39, 39, 39, 38, 38, 38, 38],
     '90th': [43, 44, 45, 45, 45, 46, 46, 46, 47, 47],
      avg: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
    }
  },
];
const output = data[0];
const keys = Object.keys(data[0].seatChartResults);
for ( let i = 0 ; i < keys.length ; i++) {
for ( let j = 0 ; j < data[0].seatChartResults[keys[i]].length ; j++) {

output.seatChartResults[keys[i]][j] = (data[0].seatChartResults[keys[i]][j] + data[1].seatChartResults[keys[i]][j])/2;
}
}

console.log(output);

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.