Home > Mobile >  Best practices for summing up values inside JSON objects in an array in JavaScript
Best practices for summing up values inside JSON objects in an array in JavaScript

Time:09-30

I have a JSON object like this, let's call it "testJson":

{
"property1": [{
        "id": "abc",
        "category": "recordsCount1"
    }, {
        "id": "def",
        "category": "recordsCount2"
    }
],
"property2": [{
        "abc": 8,
        "def": 15
    }, {
        "abc": 62,
        "def": 7
    }, {
        "abc": 4,
        "def": 16
    }
]}

I want to sum up all the values in the three objects inside "property2" for both "abc" and "def" properties. For example, for the "abc" we should receive 8 62 4 = 74 and for the "def" 15 16 7 = 38.

So far I have done this with 2 for-cycles inside two different functions, like this:

function totalAbc(testJson) {
var total = 0;

for (var i = 0; i < testJson.property2.length; i  ) {
     total = total   testJson.property2[i].abc; 
}
return total;

function totalDef(testJson) {
var total1 = 0;

for (var i = 0; i < testJson.property2.length; i  ) {
     total1 = total1   testJson.property2[i].def; 
}
return total1;
}

var sumUpValue = totalAbc(testJson)   totalDef(testJson);

Question

Is there a better way to do that, for example using the ids from "property1", as they are the same? The thing is, that I want to avoid using the exact property names for "abc" and "def" while I am looping through them because they are not constant and change over certain criteria.

Thanks in advance!

CodePudding user response:

You could do it by using [<prop_name>] syntax:

var obj = {
 abc: 4,
 def : 42
};

console.log(obj.abc);
console.log(obj["abc"]);

CodePudding user response:

If your objects can have other properties that are unrelated to the sum you want to make, then yes, you should use property1:

let data = {"property1": [{"id": "abc", "category": "recordsCount1"}, {"id": "def","category": "recordsCount2"}],"property2": [{"abc": 8,"def": 15}, {"abc": 62,"def": 7}, {"abc": 4,"def": 16}]};

let keys = data.property1.map(o => o.id);
let sum = data.property2.reduce((sum, o) => 
    keys.reduce((sum, key) => sum   o[key]??0, sum),
0);

console.log(sum);

CodePudding user response:

You can easily achieve the result using single loop using reduce

const obj = {
  property1: [
    {
      id: "abc",
      category: "recordsCount1",
    },
    {
      id: "def",
      category: "recordsCount2",
    },
  ],
  property2: [
    {
      abc: 8,
      def: 15,
    },
    {
      abc: 62,
      def: 7,
    },
    {
      abc: 4,
      def: 16,
    },
  ],
};

const property = obj.property1.map((o) => o.id);
const resultObj = Array.from(property, (_) => 0);

function total(testJson) {
  return obj.property2.reduce((acc, curr) => {
    property.forEach((prop, i) => (acc[i]  = curr[prop] ?? 0));
    return acc;
  }, resultObj);
}

var propsTotal = total(obj);
console.log(propsTotal);

CodePudding user response:

  1. Loop through "property2" array
  2. Loop through each individual objects keys
  3. Add each to key to sum object

const data = {
  "property2": [{
          "abc": 8,
          "def": 15
      }, {
          "abc": 62,
          "def": 7
      }, {
          "abc": 4,
          "def": 16
      }
  ]
};


function getSums(data) {
  let sums = {};
  
  for (o of data.property2) {
    for (key of Object.keys(o)) {
      if (!sums[key])
        sums[key] = 0;
    
      sums[key]  = o[key];
    }
  }
  
  return sums;
}


let result = getSums(data);
console.log(result);

CodePudding user response:

Well, I wrote a function called total() that does what you want it to.

I pass the property names and the source array to total(), and it gives me back a new object naming the totals, like total( array, ['property1','property2']) gives me { "property1": 77, "property2": 42 }.

But, since I think you are looking to learn, not just get the answer, I recommend reading about Array.reduce(), Array.map(), and Object.fromEntries().

You can see the way I used these to solve the problem below. Once you have read about the functions, I hope my answer will make sense. (Using these array functions is challenging, so please be patient in trying to master them.)

const testJSON = {
    "property1": [{
            "id": "abc",
            "category": "recordsCount1"
        }, {
            "id": "def",
            "category": "recordsCount2"
        }
    ],
    "property2": [{
            "abc": 8,
            "def": 15
        }, {
            "abc": 62,
            "def": 7
        }, {
            "abc": 4,
            "def": 16
        }
    ]
}

function total( array, properties ) {

    const entries = properties.map(
        propertyName => [
            propertyName,
            array.reduce( 
                ( sum, entry ) => sum   entry[ propertyName ], 
                0 
            )
        ]
    );

    return Object.fromEntries( entries );

}

console.log( total( testJSON.property2, [ 'abc', 'def' ] ) );

CodePudding user response:

Array.reduce can easily solve your problem.

const input = {
  "property1": [{
    "id": "abc",
    "category": "recordsCount1"
  }, {
    "id": "def",
    "category": "recordsCount2"
  }],
  "property2": [{
    "abc": 8,
    "def": 15
  }, {
    "abc": 62,
    "def": 7
  }, {
    "abc": 4,
    "def": 16
  }]
};

var sumProps = input.property2.reduce((acc, item) => {
   for (prop in item) {
      if (prop in acc) {
         acc[prop]  = item[prop];
      } else {
         acc[prop] = item[prop];
      }
   }
   return acc;
}, {});

console.log(sumProps);

var totalSum = 0;
for (item in sumProps) {
  totalSum  = sumProps[item];
}
console.log(totalSum);

  • Related