【问题标题】:JavaScript sum multidimensional array element valuesJavaScript 对多维数组元素值求和
【发布时间】:2016-03-08 16:30:35
【问题描述】:

我有以下数组,我需要计算每组值的总和。我可以在数组的 dataArr[1] 处获得每个组的第一个值的总和,但我还需要在数组中的每个组的 dataArr[2] 处获得第二个值的总和。

var dataArr = [    [
    "Group One",
    1,
    1
],
[
    "Group Four",
    0,
    1
],
[
    "Group Three",
    0,
    1
],
[
    "Group Three",
    1,
    0
],
[
    "Group Four",
    0,
    1
],
[
    "Group Two",
    2,
    1
],
[
    "Group Four",
    1,
    0
],
[
    "Group Three",
    0,
    1
],
[
    "Group Three",
    0,
    1
],
[
    "Group One",
    1,
    0
],
[
    "Group Three",
    0,
    1
],
[
    "Group Two",
    1,
    0
]
];

如何计算第二个值的总和并生成如下所示的多维数组:

[["Group One", 2, 1], ["Group Four", 1, 2], ["Group Three", 1, 4], ["Group Two", 3, 1]]

下面是我的代码灵感来自here:

var result = [];

$(dataArr).each(function() {
    var key = this[0];
    var value = this[1];

    if (result[key]) {
        result[key] += value;       
    } else {
        result[key] = value;
    }
});

【问题讨论】:

    标签: javascript arrays


    【解决方案1】:

    这个提议使用一个临时对象来引用结果数组。

    var dataArr = [["Group One", 1, 1], ["Group Four", 0, 1], ["Group Three", 0, 1], ["Group Three", 1, 0], ["Group Four", 0, 1], ["Group Two", 2, 1], ["Group Four", 1, 0], ["Group Three", 0, 1], ["Group Three", 0, 1], ["Group One", 1, 0], ["Group Three", 0, 1], ["Group Two", 1, 0]],
        result = function (data) {
            var r = [], o = {};
            data.forEach(function (a) {
                if (!o[a[0]]) {
                    o[a[0]] = [a[0], 0, 0];
                    r.push(o[a[0]]);
                }
                o[a[0]][1] += a[1];
                o[a[0]][2] += a[2];
            });
            return r;
        }(dataArr);
        
    document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

    【讨论】:

      【解决方案2】:

      使用Array.forEachObject.keysArray.map 方法的解决方案:

      var keys_obj = {}, key;
      dataArr.forEach(function(v){
          key = v[0];
          if (! (key in keys_obj) ) {
              keys_obj[key] = [v[1], v[2]];
          } else {
              keys_obj[key][0] += v[1];
              keys_obj[key][1] += v[2];
          }
      });
      
      var result = [];
      result = Object.keys(keys_obj).map(function(v){
          return [v, keys_obj[v][0], keys_obj[v][1]];
      });
      
      console.log(result);
      
      // the output: 
      [["Group Four", 1, 2], ["Group Three", 1, 4], ["Group One", 2, 1], ["Group Two", 3, 1]]
      

      【讨论】:

      • 为了减少括号的疯狂,我个人建议保留key 变量。
      • @Phrogz,为方便起见添加了 key 变量
      【解决方案3】:

      使用mapreduce 方法:

      var reduced = dataArr.reduce(function(obj,item) {
        if(obj.hasOwnProperty(item[0])) {
          obj[item[0]][0] += item[1]
          obj[item[0]][1] += item[2]
        } else {
          obj[item[0]] = []
          obj[item[0]][0] = item[1]
          obj[item[0]][1] = item[2]
        }
        return obj;
      }, {});
      var grouped = Object.keys(reduced).map(function(item) {
        return [item, reduced [item][0], reduced [item][1]]
      });
      

      【讨论】:

        【解决方案4】:
        1. 使用对象而不是数组来跟踪自定义属性。
        2. 每个键使用一个数组,而不是每个键一个值。现在,您可以支持每个对象 1、2 或 47 个值。
        3. 如果您将来有超过 2 个值,我建议使用 for 循环来通用处理它们。

        var dataArr = [["Group One",1,1],["Group Four",0,1],["Group Three",0,1],
                       ["Group Three",1,0],["Group Four",0,1],["Group Two",2,1],
                       ["Group Four",1,0],["Group Three",0,1],["Group Three",0,1],
                       ["Group One",1,0],["Group Three",0,1],["Group Two",1,0]];
        
        var sumByKey = {};
        dataArr.forEach(function(item){
          var key = item[0];
          if (!sumByKey[key]) sumByKey[key] = [];
          for (var i=0;i<2;++i){
            sumByKey[key][i] = (sumByKey[key][i] || 0) + item[i+1];
          }
        });
        
        var output = neatJSON(sumByKey,{wrap:30,short:true,aligned:true});
        document.querySelector('pre').innerHTML = output;
        <script src="http://phrogz.net/JS/neatjson/neatjson.js"></script>
        <pre></pre>

        【讨论】:

          【解决方案5】:

          带有对象和Array.prototype.forEach()方法

          var o = {};
          dataArr.forEach(function(e) {
              var t = o[e[0]];
              if (t) {
                  t.first += e[1];
                  t.second += e[2];
              } else {
                  t = {};
                  t.first = e[1];
                  t.second = e[2];
                  o[e[0]] = t;
              }
          });
          

          用法:

          console.log(o["Group Four"].first); // first sum for "Group Four"
          console.log(o["Group Four"].second); // second sum for "Group Four"
          
          console.log(o); // all groups with their sums
          

          【讨论】:

            【解决方案6】:

            使用Map 对象以及reducemap 函数来解决这个老问题(并且看似常见)的另一种方法。

            const dataArr = [
              ['Group One', 1, 1],
              ['Group Four', 0, 1],
              ['Group Three', 0, 1],
              ['Group Three', 1, 0],
              ['Group Four', 0, 1],
              ['Group Two', 2, 1],
              ['Group Four', 1, 0],
              ['Group Three', 0, 1],
              ['Group Three', 0, 1],
              ['Group One', 1, 0],
              ['Group Three', 0, 1],
              ['Group Two', 1, 0],
            ];
            
            const sumArray = (data) =>
              Array.from(
                data.reduce((accum, item) => {
                  let prev = accum.get(item[0]) || [0, 0];
                  accum.set(item[0], [prev[0] + item[1], prev[1] + item[2]]);
            
                  return accum;
                }, new Map())
              ).map((entry) => [entry[0], entry[1][0], entry[1][1]]);
            
            console.log(sumArray(dataArr));

            Map 实例用作reduce 中的累加器,它存储每个“组”总和的“元组”,然后将其转换为数组并映射(无双关)以展平将其转换为与原始数据相同的[[string, number, number]] 形状。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-08-11
              • 1970-01-01
              • 1970-01-01
              • 2015-10-30
              • 1970-01-01
              • 2018-09-07
              • 2018-04-11
              相关资源
              最近更新 更多