【问题标题】:Best practices for summing up values inside JSON objects in an array in JavaScript在 JavaScript 中对数组中 JSON 对象内的值求和的最佳实践
【发布时间】:2021-11-22 08:48:26
【问题描述】:

我有一个这样的 JSON 对象,我们称之为“testJson”:

{
"property1": [{
        "id": "abc",
        "category": "recordsCount1"
    }, {
        "id": "def",
        "category": "recordsCount2"
    }
],
"property2": [{
        "abc": 8,
        "def": 15
    }, {
        "abc": 62,
        "def": 7
    }, {
        "abc": 4,
        "def": 16
    }
]}

我想为“abc”和“def”属性总结“property2”内三个对象中的所有值。例如,对于“abc”,我们应该收到 8 + 62 + 4 = 74,对于“def”,我们应该收到 15 + 16 + 7 = 38。

到目前为止,我已经在两个不同的函数中使用了 2 个 for 循环,如下所示:

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);

问题

有没有更好的方法来做到这一点,例如使用“property1”中的 id,因为它们是相同的?问题是,我想避免在循环遍历它们时使用“abc”和“def”的确切属性名称,因为它们不是恒定的并且会根据某些标准进行更改。

提前致谢!

【问题讨论】:

  • 我删除了json 标签(参见json 标签的使用说明)。

标签: javascript arrays function for-loop


【解决方案1】:

您可以使用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);

【讨论】:

  • 发帖者要求避免使用确切的属性名称“abc”和“def”。
  • @MichaelG 我已经根据 OP 的需要更新了答案
【解决方案2】:
  1. 循环遍历“property2”数组
  2. 遍历每个单独的对象键
  3. 将每个键添加到 sum 对象

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);

【讨论】:

    【解决方案3】:

    您可以使用[&lt;prop_name&gt;] 语法来做到这一点:

    var obj = {
     abc: 4,
     def : 42
    };
    
    console.log(obj.abc);
    console.log(obj["abc"]);
    

    【讨论】:

      【解决方案4】:

      如果您的对象可以具有与您想要的总和无关的其他属性,那么是的,您应该使用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);

      【讨论】:

        【解决方案5】:

        Array.reduce可以轻松解决您的问题。

        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);

        【讨论】:

          【解决方案6】:

          好吧,我编写了一个名为 total() 的函数,它可以满足您的要求。

          我将属性名称和源数组传递给total(),它给了我一个新的对象来命名总数,比如total( array, ['property1','property2'])给了我{ "property1": 77, "property2": 42 }

          但是,由于我认为您希望学习,而不仅仅是获得答案,我建议您阅读有关 Array.reduce()Array.map()Object.fromEntries() 的信息。

          您可以在下面看到我使用这些解决问题的方式。一旦您阅读了这些功能,我希望我的回答会有意义。 (使用这些数组函数具有挑战性,请耐心尝试掌握它们。)

          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' ] ) );
          

          【讨论】:

            猜你喜欢
            • 2011-12-18
            • 1970-01-01
            • 1970-01-01
            • 2015-09-20
            • 2011-12-08
            • 2021-02-18
            • 2014-03-21
            • 1970-01-01
            • 2018-05-26
            相关资源
            最近更新 更多