Reputation: 7652
If this is my object
{
"a":{
"a1":5,
"b":{
"b1":10,
"b2":15,
"c":{
"c1":15
}
}
}
}
the output I want is:
{a:45 b:40, c: 15}
c => 15
b => 10 + 15 + c
a => 5 + b + c
how do I achieve this? been banging my head against a brick wall all day
so far I've tried:
let constructedTotals = {};
const calculateVals = (vals) => {
return vals
.map((val) => {
if (typeof val === "object" && Object.keys(val).length > 0) {
return Object.values(val);
}
return val;
})
.flatMap((x) => x)
.filter((x) => typeof x === "number")
.reduce((a, b) => a + b, 0);
};
const constructing = (construct) => {
return Object.entries(construct).map((entry) => {
if (typeof entry[1] === "object") {
constructing(entry[1]);
constructedTotals = {
...constructedTotals,
[entry[0]]: calculateVals(Object.values(entry[1])),
};
} else {
console.log('here')
}
});
};
Upvotes: 0
Views: 201
Reputation: 364
you can try this:
let obj = {
"a":{
"a1":5,
"b":{
"b1":10,
"b2":15,
"c":{
"c1":15
}
}
}
}
let recusive = (obj,output)=>{
if(typeof(obj) == "object"){
let keys = Object.keys(obj)
let sum = 0;
keys.forEach(key => {
if(typeof(obj[key]) == "object"){
output[key] = recusive(obj[key],output)
sum += output[key]
}
else
sum+= obj[key]
});
return sum
}
else
return obj;
}
let warp = (obj) => {
let output = {};
recusive(obj, output);
return output;
}
console.log(warp(obj))
The output will hold the result, it worked for the example you gave, might throw if you give it an object that is build differently
Upvotes: 0
Reputation: 48620
You could create a reducer function that:
const main = () => {
const result = reduce(tree, (acc, node) => {
let currKey, prevKey, currVal = 0;
for (const prop in node) {
const [, key] = prop.match(/^(\w)\d$/) ?? [];
currKey ??= key;
if (key) currVal += +node[prop];
prevKey ??= prop.match(/^(\w)$/)?.[1];
}
if (currKey) {
acc[currKey] = (acc[prevKey] ?? 0) + currVal;
}
});
console.log(result); // { "c": 15, "b": 40, "a": 45 }
};
const reduce = (node, visitor) => {
const result = {};
traverse(node, visitor, result);
return result;
};
const traverse = (node, visitor, result) => {
if (typeof node === 'object') {
for (const prop in node) {
traverse(node[prop], visitor, result);
}
}
visitor(result, node);
};
const tree = {
a: {
a1: 5,
b: {
b1: 10,
b2: 15,
c: {
c1: 15
}
}
}
};
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
Upvotes: 0
Reputation: 386624
You could handover the parent key and add the total of nested keys.
const
sum = (object, parent = '') => Object
.entries(object)
.reduce((r, [k, v]) => {
if (v && typeof v === 'object') {
Object.assign(r, sum(v, k));
if (parent) r[parent] += r[k];
} else {
r[parent] = (r[parent] || 0) + v;
}
return r;
}, {}),
data = { a: { a1: 5, b: { b1: 10, b2: 15, c: { c1: 15 } } } },
result = sum(data);
console.log(result);
Upvotes: 1
Reputation: 1628
const data = {
a: {
a1: 5,
b: {
b1: 10,
b2: 15,
c: {
c1: 15,
},
},
},
};
const outputObj = {};
function addValue(data) {
for (const [key, value] of Object.entries(data)) {
const outKey = key.at(0);
outputObj[outKey] ??= 0;
if (typeof value === "object") addValue(value);
else for (const svKey in outputObj) outputObj[svKey] += value;
}
}
addValue(data);
console.log(outputObj);
Upvotes: 1