【问题标题】:Group and average array values based on index根据索引对数组值进行分组和平均
【发布时间】:2019-05-16 14:01:10
【问题描述】:

我有一个包含字符串和整数的二维数组。 在 GAS 中,我想创建一个新数组,对具有公共字符串的数组的整数进行平均。

我一直在寻找解决方案,但我发现的大部分是在 GAS 不支持的 ES6 上,其余的我无法适应我的情况。

我尝试使用 map、reduce 和 filter,但找不到合适的解决方案。

以下是数组和所需输出的示例。

function myfunction(){

var array = [
["House1", 1.0, 2.0, 5.0, 1.0], 
["House1", 1.0, 4.0, 2.0, 3.0], 
["House2", 2.0, 3.0, 3.0, 4.0], 
["House2", 5.0, 4.0, 3.0, 4.0],
["House2", 4.0, 5.0, 2.0, 2.0], 
["House3", 2.0, 1.0, 4.0, 5.0]]
}
//Desired output

var newArray = [
["House1", 1.0, 3.0, 3.5, 2.0],
["House2", 3.6, 4.0, 2.6, 3.3],
["House3", 2.0, 1.0, 4.0, 5.0]
]

【问题讨论】:

  • ES5 能用吗?

标签: javascript google-apps-script


【解决方案1】:

let array = [
  ["House1", 1.0, 2.0, 5.0, 1.0],
  ["House1", 1.0, 4.0, 2.0, 3.0],
  ["House2", 2.0, 3.0, 3.0, 4.0],
  ["House2", 5.0, 4.0, 3.0, 4.0],
  ["House2", 4.0, 5.0, 2.0, 2.0],
  ["House3", 2.0, 1.0, 4.0, 5.0]];

let averageArrays = arrays =>
    arrays.reduce((sum, a) => {
      a.forEach((v, i) => sum[i] = (sum[i] || 0) + v / arrays.length);
      return sum;
    }, []);

let grouped = array.reduce((acc, a) => {
  acc[a[0]] = acc[a[0]] || [];
  acc[a[0]].push(a.slice(1));
  return acc;
}, {});

let averages = Object.entries(grouped).map(([name, arrays]) => [name, ...averageArrays(arrays)]);

console.log(averages);

【讨论】:

  • 您是否尝试过单击“运行代码 sn-p”按钮?错误?我的解决方案没有特定于 GAS 的内容。将 es6 转换为 es5 不是我负责 imo 的事情。
【解决方案2】:

您可以为相同的组获取一个哈希表,并通过存储总和和计数来获取平均值。

结果是每个组的平均值数组。

function buildAverages(array) {
    var hash = {},
        result = [],
        i, j, item, key;
        
    for (i = 0; i < array.length; i++) {
        item = array[i];
        key = item[0];
        if (!hash[key]) {
            hash[key] = { avg: array[i].slice(), sums: array[i].slice(), count: 1 };
            result.push(hash[key].avg);
            continue;
        }
        hash[key].count++;
        for (j = 1; j < item.length; j++) {
            hash[key].sums[j] += item[j];
            hash[key].avg[j] = (hash[key].sums[j] / hash[key].count);
        }
    }
    return result;
}

var array = [["House1", 1.0, 2.0, 5.0, 1.0], ["House1", 1.0, 4.0, 2.0, 3.0], ["House2", 2.0, 3.0, 3.0, 4.0], ["House2", 5.0, 4.0, 3.0, 4.0], ["House2", 4.0, 5.0, 2.0, 2.0], ["House3", 2.0, 1.0, 4.0, 5.0]]
  
console.log(buildAverages(array));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    下面的代码是在GAS环境下测试的。

    function myFunction() {
      var array = [
        ["House1", 1.0, 2.0, 5.0, 1.0], 
        ["House1", 1.0, 4.0, 2.0, 3.0], 
        ["House2", 2.0, 3.0, 3.0, 4.0], 
        ["House2", 5.0, 4.0, 3.0, 4.0],
        ["House2", 4.0, 5.0, 2.0, 2.0], 
        ["House3", 2.0, 1.0, 4.0, 5.0]
      ];
    
      var avg = {}, count = {};
      array.forEach(function(a) {
        var key = a.shift();
        if (avg[key]) {
          for (var i = 0; i < 4; i++) { 
            avg[key][i] += a[i];
          }
          count[key]++;
        } else {
          avg[key] = a;
          count[key] = 1;
        }
      });
    
      var result = [];
      for (var key in avg) {
        for (var i = 0; i < 4; i++) { 
          avg[key][i] /= count[key];
        }
        avg[key].unshift(key);
        result.push(avg[key]);
      }
    
      Logger.log(result);
    }
    

    可能会,虽然很长,但每一步都很清楚。我们在 avgcount 对象中累积中间结果,这些对象会根据需要转换为 result 数组。

    【讨论】:

      【解决方案4】:

      为每个房子创建一个数组的分组对象。获取每个组对象并将它们求和,然后为每个对象单独平均。

      function groupByAndAvg(array) {
        var out = {};
        array.forEach(function(row) {
          var house = row[0];
          out[house] = out[house] || [];
          out[house].push(row);
        });
        return Object.keys(out).map(function(thisHouse) {
          var house = out[thisHouse];
          var l = house.length;
          var sumHouse = house.reduce(function(acc, row) {
            return acc.map(function(e, i) {
              return typeof e === 'number' ? e + row[i] : e;
            });
          }, house.pop());
          return sumHouse.map(function(e) {
            return typeof e === 'number' ? e / l : e;
          });
        });
      }
      var array = [
        ['House1', 1.0, 2.0, 5.0, 1.0],
        ['House1', 1.0, 4.0, 2.0, 3.0],
        ['House2', 2.0, 3.0, 3.0, 4.0],
        ['House2', 5.0, 4.0, 3.0, 4.0],
        ['House2', 4.0, 5.0, 2.0, 2.0],
        ['House3', 2.0, 1.0, 4.0, 5.0],
      ];
      console.info(groupByAndAvg(array));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-29
        • 2017-03-01
        • 2021-11-02
        • 2016-05-26
        • 1970-01-01
        • 2020-10-13
        • 2021-02-07
        • 1970-01-01
        相关资源
        最近更新 更多