简体   繁体   中英

How to find sum of a specific property in nested JS object

I want to calculate the total sum of all the 'val' in this object. The final output should be 113. I tried searching but couldn't find a similar problem on stackoverflow.

 const object = { val: 10, child: [ { val: 20, child: [ { val: 25, child: [] }, { val: 28, child: [] } ] }, { val: 30, child: [] } ] };

What I tried is this. I know this is not the best approach and would love to see a better approach to this.

 const object = { val: 10, child: [ { val: 20, child: [ { val: 25, child: [] }, { val: 28, child: [] } ] }, { val: 30, child: [] } ] }; function sum() { let k = object.val; if(object.child.length>0){ object.child.map(item => { k += item.val; if(item.child.length>0){ item.child.map(item => k += item.val) } }) } return k } const result = sum(object); console.log(result);

You can find the problem here - https://codesandbox.io/s/young-night-ulnfl?file=/src/index.js

I was also thinking something like flat() could have helped but that is only for arrays.

Recursive Array#reduce()

 const object = { val: 10, child: [{ val: 20, child: [{ val: 25, child: [] }, { val: 28, child: [] }] }, { val: 30, child: [] }] }; const sumObjectVals = (arr) => arr .reduce((a, obj) => ( a += (obj.child.length ? obj.val + sumObjectVals(obj.child) : obj.val), a), 0); console.log(sumObjectVals([object]))

const object = {
  val: 10,
  child: [
    {
      val: 20,
      child: [
        {
          val: 25,
          child: []
        },
        {
          val: 28,
          child: []
        }
      ]
    },
    {
      val: 30,
      child: []
    }
  ]
};

function sum(obj, summ) {
  summ += obj.val;

  if(obj.child.length > 0) {
    obj.child.forEach(x => summ = sum(x, summ))
  }

  return summ;
}

const result = sum(object, 0);
console.log(result);

You could create a recursive node visitor function.

 const tree = { val: 10, child: [{ val: 20, child: [{ val: 25, child: [] }, { val: 28, child: [] }] }, { val: 30, child: [] }] } const visitNodes = (obj, visitor, key) => { if (typeof obj === 'object') { for (let key in obj) { visitNodes(obj[key], visitor, key); } } else { visitor(obj, key); } }; let total = 0; visitNodes(tree, (val, key) => { if (key === 'val') { total += val; } }); console.log(`Total: ${total}`);

Alternatively, you could have an accumulator that can add all your values for you.

Edit: Altered the function signature to take a custom "child" prop.

 const tree = { val: 10, child: [{ val: 20, child: [{ val: 25, child: [] }, { val: 28, child: [] }] }, { val: 30, child: [] }] } const accumulateValues = (obj, visitor, childProp = null, acc = 0) => { if (typeof obj === 'object') { acc += visitor(obj); if (Array.isArray(obj[childProp])) { acc += obj[childProp].reduce((acc, child) => accumulateValues(child, visitor, childProp, acc), 0); } } return acc; }; const total = accumulateValues(tree, ({ val }) => val, 'child'); console.log(`Total: ${total}`);

// You can use multiple reduce array method to get the result.

 const object = { val: 10, child: [ { val: 20, child: [ { val: 25, child: [] }, { val: 28, child: [] } ] }, { val: 30, child: [] } ] }; const results = object.child.reduce((totals, current)=> { const innerResult = current.child.reduce((total, cur) => { return total + cur.val }, 0); return totals + current.val + innerResult; }, object.val); console.log(results);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM