根据索引分组和平均数组值

时间:2019-05-16 14:01:11

标签: javascript google-apps-script

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

我一直在寻找解决方案,但是我发现的大部分内容都在ES6上,而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]
]

4 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

下面的代码在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);
}

可能很长,但每个步骤都很明确。我们在 av count 对象中累积中间结果,然后根据需要将其转换为 result 数组。

答案 3 :(得分:0)

为每个房屋创建一个数组的分组对象。取每个组对象并求和,然后对每个对象分别求平均值。

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