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:
- Loop through "property2" array
- Loop through each individual objects keys
- 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);