【问题标题】:How to sum values of objects and push it in an array如何对对象的值求和并将其推送到数组中
【发布时间】:2015-07-15 02:45:14
【问题描述】:

我有一个动态的对象数组,取决于表中行的选择。一个例子:

var obj = [
            { name: "test1",  totalCosts: 45560, actualTotalCosts: 652112, riskCosts: 65442 },
            { name: "test2",  totalCosts: 3434,  actualTotalCosts: 25252,   riskCosts: 34234 },
            { name: "test3",  totalCosts: 23123, actualTotalCosts: 23242,  riskCosts: 0 },
        ];

生成此数组后,我想调用一个函数,该函数在此数组中再推一行并将其命名为“总计”并将所有受尊重的值相加,如下所示:

{name: "total", totalCosts:72117, actualTotalCosts:700606, riskCosts: 99676 }

obj[0].totalCosts + obj[1].totalCosts + obj[2].totalCosts = obj[3].totalCosts

我尝试用我有限的知识编写一个,但该函数不是总结所有三个对象的值,而是将整个对象总结为一个。

            function sum1( obj ) {
            var result1 = [];
            for (var i = 0; i < obj.length; i++) {
                var sum = 0, arr = [];
                for (var key in obj[i]) {
                    if (key != 'name') {
                        sum += obj[i][key];
                        arr.push(sum[key]);
                    }

                }
                result1.push(arr);
                return result1;
            }
        }

请提供一个函数,可以对所有对象求和并返回包含总数的数组。我也尝试使用 d3.sum 但没有成功。

【问题讨论】:

    标签: javascript arrays object d3.js


    【解决方案1】:

    您可以借助 d3.sum 采用函数式方法...

      obj.push(d3.keys(obj[0])                //get the keys from obj[0]
        .reduce(function(sumRow, sumCol) {    //construct a summary row
          var isNum = !isNaN(obj[0][sumCol])  //only sum numeric fields
          return (sumRow[sumCol] = (isNum ? d3.sum(obj, function(row) {
            return row[sumCol]                //accessor for the column for  d3.sum
          }) : "All"), sumRow)                //append the sum col to the sum row object
        },{}));                               //initial value for reduce is {}
    

    工作示例

      (function() {
        var obj = [{
          name: "test1",
          name2: "type1",
          totalCosts: 45560,
          actualTotalCosts: 652112,
          riskCosts: 65442
        }, {
          name: "test2",
          name2: "type2",
          totalCosts: 3434,
          actualTotalCosts: 25252,
          riskCosts: 34234
        }, {
          name: "test3",
          name2: "type3",
          totalCosts: 23123,
          actualTotalCosts: 23242,
          riskCosts: 0
        }];
    
        obj.push(d3.keys(obj[0])
          .reduce(function(sumRow, sumCol) {
            var isNum = !isNaN(obj[0][sumCol])
            return (sumRow[sumCol] = (isNum ? d3.sum(obj, function(row) {
              return row[sumCol]
            }) : "All"), sumRow)
          }, {}));
    
        d3.select("#result").text(JSON.stringify(obj))
      })()
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <div id="result"></div>

    【讨论】:

    • 不错的答案!您可能希望将列的名称从“All”更改为“total”以完全符合 OP 的要求。
    • @altocumulus 欢呼队友...是的,也许你是对的。我确实考虑过这一点,但选择了“全部”,因为我正在努力将其推广到具有任意汇总操作和排除规则的对象中。
    • 为我工作,感谢完美的回答,我的页面中已经有 d3 作为它的 Angular d3 应用程序
    • 好的,很好。对我来说,这只是另一个例子,它表明你很少会在 d3 中找不到你需要的代码。它总是值得四处看看; ECMA5 函数式编程风格是实现这一目标的强大工具。
    【解决方案2】:

    注意:重要的是要意识到您所调用的 var obj 实际上是一个数组。

    话虽如此,您可以遍历数组并执行以下操作:

    function sumAll(arr) {
    
      // Create variables for the costs we're tracking
      var totalCosts = 0;
      var actualTotalCosts = 0;
      var riskCosts = 0;
    
      arr.forEach(function(elem) {
        // At each iteration of our loop, increase the appropriate variables by their appropriate values
        if (elem.hasOwnProperty('totalCosts')) {
          totalCosts += elem.totalCosts;
        }
        if (elem.hasOwnProperty('actualTotalCosts')) {
        actualTotalCosts += elem.actualTotalCosts;
        }
        if (elem.hasOwnProperty('riskCosts')) {
          riskCosts += elem.riskCosts
        }
      });
    
      // Return an object with the information we'd like to have
      return {
        name: 'total',
        totalCosts: totalCosts,
        actualTotalCosts: actualTotalCosts,
        riskCosts: riskCosts
      }
    }
    

    来自您的代码:

    var obj = [
                { name: "test1",  totalCosts: 45560, actualTotalCosts: 652112, riskCosts: 65442 },
                { name: "test2",  totalCosts: 3434,  actualTotalCosts: 25252,   riskCosts: 34234 },
                { name: "test3",  totalCosts: 23123, actualTotalCosts: 23242,  riskCosts: 0 },
            ];
    

    调用我的函数:

    sumAll(obj) // {name: "total", totalCosts: 72117, actualTotalCosts: 700606, riskCosts: 99676}
    

    【讨论】:

    • 你不需要在 foreach 循环中使用 Objects hasOwnProperty 吗?我知道这是一个您正在循环的数组,但您正在检查 Obects 属性?
    • 你说得对,我应该在那里检查一下边缘情况。我稍后会更新我的答案。
    • hasOwnProperty() 应该接受一个字符串,而不是一个变量 totalCosts 这绝对是一个数字。
    • 行不通,totalCosts、actualCosts 是动态的,可以在用户选择不同的成本值时随时更改。
    猜你喜欢
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 2014-08-08
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多