【问题标题】:How do I merge duplicate cells together with google app script?如何将重复的单元格与谷歌应用脚​​本合并在一起?
【发布时间】:2017-06-29 14:04:45
【问题描述】:

我目前有一个包含两列的列表。第一列是学生姓名,第二列是他们的分数。

我从多个电子表格中导入了这个列表,所以学生的名字有很多重复。我可以删除重复项,但我想记录他们拥有的总分。例如:

艾米 10 鲍勃 9 卡罗尔 15 艾米 12

会变成:

艾米 22 鲍勃 9 卡罗尔 15

这是我目前所拥有的:

  var target = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = target.getSheetByName("Sheet2");
  var data = sheet.getRange("A2:B1000").getValues();
  var newData = new Array();
  var k = 0
  var finallist = []
  for(i in data){
    k++;
    var row = data[i];
    var duplicate = false;
    for(j in newData){
      if(row[0] == newData[j][0]){
        duplicate = true;
        var storedHour = sheet.getRange("B"+k).getValue();
        var position = finallist.indexOf(row[0]);
        var originalCell = sheet.getRange("B"+(position+1));
        var originalHour = originalCell.getValue();
        originalCell.setValue(originalHour + storedHour);
        sheet.getRange(k,2).setValue("")
        sheet.getRange(k,1).setValue("")
      }
    }
    if(!duplicate){
      newData.push(row);
      finallist.push(row[0])
    }
  }
}

我遇到的问题是我们有一个非常大的数据样本,我担心它可能会超过 Google 的 5 分钟最长执行时间。还有其他更有效的方法来实现我的目标吗?

【问题讨论】:

  • 您好,Qilin,有什么不符合您的预期?你遇到了什么问题?
  • 对不起,我忘了把实际问题放在描述中!多么粗心。我只是想知道如何使代码更高效,因为我想在 Google 的 5 分钟最大执行时间下执行它。我现在将其添加到说明中。
  • 哈哈,轻松搞定,不用担心。我对 Google Scripts 了解不多,但我觉得像 MapReduce 之类的东西或将任务拆分为单独的作业可能会奏效。
  • 我猜你是对的。如果超出限制,我可以将任务分成两半。谢谢!
  • 你在单元格中尝试过 =query() 吗?我想说的是,如果您选择正确的语句,那可以得到您想要的结果,但我从未在查询中使用过分组。

标签: javascript google-apps-script spreadsheet


【解决方案1】:

您的代码运行缓慢,因为电子表格 API 方法(如 getRange)耗时且比其他 JavaScript 代码慢得多。

以下是优化的函数,减少了此类电子表格 API 调用的数量:

function calcNumbers()
{
  var target = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = target.getSheetByName("Sheet2");
  var lastRow = sheet.getLastRow();
  var dataRange = sheet.getRange(2, 1, lastRow-1, 2);
  var data = dataRange.getValues();
  var pointsByName = {};

  for (var i = 0; i < data.length; i++)
  {
    var row = data[i];
    var curName = row[0];
    var curNumber = row[1];

    // empty name
    if (!curName.trim())
    {
      continue;
    }

    // if name found first time, save it to object
    if (!pointsByName[curName])
    {
      pointsByName[curName] = Number(curNumber);
    }
    // if duplicate, sum numbers
    else
    {
      pointsByName[curName] += curNumber;
    }
  }

  // prepare data for output
  var outputData = Object.keys(pointsByName).map(function(name){
    return [name, pointsByName[name]];
  });

  // clear old data
  dataRange.clearContent();

  // write calculated data
  var newDataRange = sheet.getRange(2, 1, outputData.length, 2);
  newDataRange.setValues(outputData);
}

【讨论】:

  • 类似于计数板的东西。我喜欢它。
【解决方案2】:

在比较之前排序允许每次迭代只查看下一个项目而不是所有项目。溢出的好处是入围结果是字母化的。执行时间显着减少。

function sumDups() {
  var target = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = target.getSheetByName("Sheet2");
  var data = sheet.getRange("A2:B" + sheet.getLastRow()).getValues().sort();
  var finallist = [];
  for(var i = 0; i<= data.length - 1; i++){
    var hours = data[i][1];
    while((i < data.length - 1) && (data[i][0] == data[i+1][0])) {
       hours += data[i+1][1];
       i++;
       };
    finallist.push([data[i][0], hours]);
  };
  Logger.log(finallist);
}

编辑:名称在第一列的简单数据结构允许它工作。对于任何更复杂的理解和应用@Kos 的答案中显示的方法是可取的

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    相关资源
    最近更新 更多