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!
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' ] ) );
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);
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);