父值是嵌套 javascript 对象中所有子值的总和

问题描述 投票:0回答:4

我有一个深度嵌套的 javascript 对象,其子对象的数量不受限制。每个孩子都有一个值和一个总值。 TotalValue 应该是其所有子级和子级的所有值的总和。我怎样才能做到这一点?

目前我只能使用递归函数循环整个对象:

// Recursive function
_.each(names, function(parent) { 
    if(parent.children.length > 0) { 
        recursiveFunction(parent.children);
    }
});

function recursiveFunction(children){ 
    _.each(children, function(child) { 
        if(child.children.length > 0) { 
            recursiveFunction(child.children)
        }
    });
}; 

// Deeply nested javascript object
var names = {
    name: 'name-1',
    value: 10,
    valueTotal: 0, // should be 60 (name-1.1 + name-1.2 + name-1.2.1 + name-1.2.2 + name-1.2.2.1 + name-1.2.2.2)
    children: [{
            name: 'name-1.1',
            value: 10,
            valueTotal: 0,
            children: []
        }, {
            name: 'name-1.2',
            value: 10,
            valueTotal: 0, // should be 40 (name-1.2.1 + name-1.2.2 + name-1.2.2.1 + name-1.2.2.2)
            children: [{
                name: 'name-1.2.1',
                value: 10,
                valueTotal: 0,
                children: []
            }, {
                name: 'name-1.2.2',
                value: 10,
                valueTotal: 0, // should be 20 (name-1.2.2.1 + name-1.2.2.2)
                children: [{
                    name: 'name-1.2.2.1',
                    value: 10,
                    valueTotal: 0,
                    children: []
                }, {
                    name: 'name-1.2.2.2',
                    value: 10,
                    valueTotal: 0,
                    children: []
                }]
            }]
        }]
    }
}
javascript recursion lodash
4个回答
7
投票

所以事实上你想做这样的事情: 每个 elem 都会向他的孩子询问其值,这些孩子会做同样的事情并返回他们的总值加上他们自己的值。

function sumUp(object){
  object.totalValue = 0;
  for(child of object.children){
    object.totalValue += sumUp(child);
   }
   return object.totalValue + object.value;
}

像这样开始:

const totalofall = sumUp(names);
console.log(names); //your expected result.

工作示例: http://jsbin.com/laxiveyoki/edit?console


2
投票

您可以使用带有迭代和递归方法的纯 JavaScript,并对本地总数进行一些健全性检查。

function calculateValues(o) {
    o.valueTotal = (o.children || []).reduce(function (r, a) {
        calculateValues(a);				
        return r + (a.value || 0) + (a.valueTotal || 0);
    }, 0);
}

var names = { name: 'name-1', value: 10, valueTotal: 0, children: [{ name: 'name-1.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2', value: 10, valueTotal: 0, children: [{ name: 'name-1.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2', value: 10, valueTotal: 0, children: [{ name: 'name-1.2.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2.2', value: 10, valueTotal: 0, children: [] }] }] }] };

calculateValues(names);
console.log(names);
.as-console-wrapper { max-height: 100% !important; top: 0; }


0
投票

不太喜欢重新发明轮子,并建议使用库来提高可读性和可维护性。我们现在使用 object-scan 进行大部分数据处理。一旦您了解如何使用它,它的用途就非常广泛。无论如何,这是您问题的可能解决方案

// const objectScan = require('object-scan');

const injectSums = (data) => {
  objectScan(['**.children'], {
    filterFn: ({ parent, value: children }) => {
      parent.valueTotal = children
        .map(({ valueTotal, value }) => valueTotal + value)
        .reduce((a, b) => a + b, 0);
    }
  })(data);
};

const names = { name: 'name-1', value: 10, valueTotal: 0, children: [ { name: 'name-1.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2', value: 10, valueTotal: 0, children: [ { name: 'name-1.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2', value: 10, valueTotal: 0, children: [ { name: 'name-1.2.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2.2', value: 10, valueTotal: 0, children: [] } ] } ] }] };

injectSums(names);

console.log(names);
// => { name: 'name-1', value: 10, valueTotal: 60, children: [ { name: 'name-1.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2', value: 10, valueTotal: 40, children: [ { name: 'name-1.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2', value: 10, valueTotal: 20, children: [ { name: 'name-1.2.2.1', value: 10, valueTotal: 0, children: [] }, { name: 'name-1.2.2.2', value: 10, valueTotal: 0, children: [] } ] } ] } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

免责声明:我是object-scan

的作者

0
投票

这对我有用。它将对象中先前的计数值添加到总计数中。这个可以稍后减去

function sumUpTree(
  obj,
  { key = "count", totalKey = "totalCount", childrenKey = "children" }
) {
  obj[totalKey] =
    obj[key] +
    (obj[childrenKey] || []).reduce(function (r, child) {
      sumUpTree(child);
      return r + (child[totalKey] || 0);
    }, 0);
}

这受到以上 Jonas WilmsNina Scholz

的回答的启发
© www.soinside.com 2019 - 2024. All rights reserved.