0

I have a an array consist of datas , where each datas has multiple subDatas,

var res = [
    {
        data1:{subData1:56, subData2:0, subData3:45},
        data2:{subData2:565, subData3:67, subData4:45},
        data3:{subData1:45, subData3:0},
        data4:{subData1:32, subData2:0, subData3:47},
        data5:{subData1:107, subData2:34, subData3:65},
        data6:{subData3:123, subData4:43},
        data7:{subData1:432, subData2:67, subData3:78},
        data8:{subData4:23, subData5:432, subData6:654},

    }
  ];

i need to get the sum of each subDatas in an array, i have figured out the solution but how can i reduce the code . Please find the below code for solving and suggest a better optimized way. I am using underscore js too.

var res = [
    {
        data1:{subData1:56, subData2:0, subData3:45},
        data2:{subData2:565, subData3:67, subData4:45},
        data3:{subData1:45, subData3:0},
        data4:{subData1:32, subData2:0, subData3:47},
        data5:{subData1:107, subData2:34, subData3:65},
        data6:{subData3:123, subData4:43},
        data7:{subData1:432, subData2:67, subData3:78},
        data8:{subData4:23, subData5:432, subData6:654},

    }
  ];
  var values = Object.values(res[0])
  var arrayOfItems = [];
  var sums = {};

  values.map(obj => Object.keys(obj)).map(item => {item.map(subItem => arrayOfItems.push(subItem))})
 
  arrayOfItems = _.uniq(arrayOfItems)

  _.each(values, function (item) {
      _.each(arrayOfItems, function (color) {
          if(sums.hasOwnProperty(color)){
              sums[color] = sums[color]  + ( item[color] ? item[color] : 0 )
          }else{
              sums[color] = 0 + (item[color] ? item[color] : 0)
          }
      });
  });
  
  
  
  var arrOfSubDatasTotal = Object.keys(sums).map(item => ({name:item, total:sums[item]}))
  
  var totalOfSubDatas = Object.values(sums).reduce((a,b) => a + b)
  
  
  console.log("array Of SubDatas Total =>", arrOfSubDatasTotal)
  
    console.log("total Of SubDatas =>", totalOfSubDatas)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

2

3 Answers 3

0

You can use the Sum monoid to whip through that list

import propOr from 'crocks/helpers/propOr'
import curry from 'crocks/helpers/curry'
import mreduceMap from 'crocks/helpers/mreduceMap'
import Sum from 'crocks/Sum'

var res = [{
  data1:{subData1:56, subData2:0, subData3:45},
  data2:{subData2:565, subData3:67, subData4:45},
  data3:{subData1:45, subData3:0},
  data4:{subData1:32, subData2:0, subData3:47},
  data5:{subData1:107, subData2:34, subData3:65},
  data6:{subData3:123, subData4:43},
  data7:{subData1:432, subData2:67, subData3:78},
  data8:{subData4:23, subData5:432, subData6:654},
}];

const data = Object.values(res[0])

const getSubData = i => propOr(0, 'subData' + i)

const getDataSum = curry(i => mreduceMap(Sum, getSubData(i)))


console.log(getDataSum(1, data))
// 672 - the sum of all subData1 properties in the list
Sign up to request clarification or add additional context in comments.

Comments

0

You can try this in pure JS. Hope it helps.

const res = [{
    data1:{subData1:56, subData2:0, subData3:45},
    data2:{subData2:565, subData3:67, subData4:45},
    data3:{subData1:45, subData3:0},
    data4:{subData1:32, subData2:0, subData3:47},
    data5:{subData1:107, subData2:34, subData3:65},
    data6:{subData3:123, subData4:43},
    data7:{subData1:432, subData2:67, subData3:78},
    data8:{subData4:23, subData5:432, subData6:654},
}];

const sums = {};

// For each item on your array

res.forEach((item) => {

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

       Object.keys(item[key]).forEach((sub) => {
           
           // Initialize its position on the sum object
           
           if (!sums[sub]) sums[sub] = { sum: 0, name: sub };

            sums[sub].sum += item[key][sub];
       });
   });
});

// Get the total of the subData
const total = Object.values(sums).reduce((acc, val) => acc += val.sum, 0.0);

console.log('Sums', Object.values(sums));
console.log('Total', total);

Comments

0

Try following using Array.reduce, Array.forEach, Array.map, Object.values, Object.entries

LOGIC

Create an object with keys as subData{number} and value as the sum of its values.

To create object, use Array.reduce to iterate over each object in array and then Object.values to get all the values in the object. Iterate over each value using Array.forEach and then for each object, use Object.entries to add / update the entry in intermediate object (reduce accumulator).

While creating the object, sum all the values to create the total of all the subData's. Finally transform object to array using Object.entries and use Array.map to convert it into the desired format.

var res = [{data1:{subData1:56, subData2:0, subData3:45},data2:{subData2:565, subData3:67, subData4:45},data3:{subData1:45, subData3:0},data4:{subData1:32, subData2:0, subData3:47},data5:{subData1:107, subData2:34, subData3:65},data6:{subData3:123, subData4:43},data7:{subData1:432, subData2:67, subData3:78},data8:{subData4:23, subData5:432, subData6:654}}];

let total = 0;
let result = Object.entries(
      res.reduce((a,c) => {
          Object.values(c).forEach(
              o => Object.entries(o).forEach(([k,v]) => {
                  a[k] = (a[k] || 0) + v;
                  total += v;
              })
          );
          return a;
      }, {})
  ).map(([k,v]) => ({name: k, total : v}));
  
console.log(result);
console.log(total);

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.