【问题标题】:Java script optimization for a google apps script谷歌应用脚​​本的 Javascript 优化
【发布时间】:2020-06-15 11:57:06
【问题描述】:

我有下面的工作代码,它比较来自两个不同工作表的两组数据。一个是 395 个电话号码的列表,第二个是大约 135,000 行数据的列表。以下代码比较两者的相似性并将相似的行复制到第三张表。

虽然代码确实适用于小规模测试(1000 行和 395 个电话号码),但大约需要 10 分钟。但是,执行 135,000 行会使脚本超时。这是下面的脚本。

`function copyRowtoSheet3() { 
  var s1 = SpreadsheetApp.openById("1Aw11LiKzyezfrTQIuTsJPhUFtz8RPqLCc8FlIiy0ZlE").getSheetByName('Sheet1');
  var s2 = SpreadsheetApp.openById("1Aw11LiKzyezfrTQIuTsJPhUFtz8RPqLCc8FlIiy0ZlE").getSheetByName('Sheet2'); 
  var s3 = SpreadsheetApp.openById("1Aw11LiKzyezfrTQIuTsJPhUFtz8RPqLCc8FlIiy0ZlE").getSheetByName('Sheet3'); 
  var values1 = s1.getDataRange().getValues();
  var values2 = s2.getDataRange().getValues();
  var resultArray = [];
  for(var n=0; n < values1.length ; n++){
    var keep = false;
    for(var p=0; p < values2.length ; p++){
      Logger.log(values1[n][0]+' =? '+values2[p][0]);
      if( values1[n][1] == values2[p][0] ){
        resultArray.push(values1[n]);
        Logger.log('true');
        //break ;
      }
    }
  }  
  s3.getRange(+1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}`

我不是最擅长优化代码,如果有任何建议可以在这里输入,我会很高兴。我查看了最佳实践,并已尽我所能应用它们。对这里的代码有什么建议吗?

【问题讨论】:

  • 大约 10 分钟 真的吗?对于 1000 行?执行超时为 6 分钟
  • 据我了解,付费企业帐户的超时时间为 30 分钟。 6 分钟未付费。
  • 虽然这是真的,但您的脚本不太可能只运行 10 分钟 1k 行
  • 脚本在 10 分钟内运行小规模测试。但是,其他人提供帮助的脚本修改将时间缩短到 30 秒左右。干杯!

标签: javascript optimization google-apps-script google-sheets


【解决方案1】:
  • 您想要比较“Sheet1”的“B”列和“Sheet2”的“A”列。
  • 当“Sheet1”的“B”列和“Sheet2”的“A”列的值相同时,要将“Sheet1”的行放到“Sheet3”中。
  • 您想降低脚本的处理成本。
  • 您希望使用 Google Apps 脚本实现此目的。

如果我的理解是正确的,那么这个答案呢?请认为这只是几个可能的答案之一。

修改点:

  • 请使用SpreadsheetApp.openById("1Aw11LiKzyezfrTQIuTsJPhUFtz8RPqLCc8FlIiy0ZlE")一次。
  • 在您的情况下,values2 用于 for 循环。所以values2 循环values1 的每个元素。
    • 为此,准备了一个对象用于搜索值。
  • 如果resultArray 的长度很大,可以使用Sheets API 而不是像SpreadsheetApp 这样的电子表格服务来降低处理成本。 Ref

当以上几点反映到您的脚本中时,流程如下。

流动:
  1. 从“Sheet1”和“Sheet2”中检索值,
  2. 使用values2创建一个对象。
  3. 使用values1 和对象创建resultArray
  4. 使用 Sheets API 中的 spreadsheets.values.update 方法将 resultArray 放入“Sheet3”。

修改脚本:

在你使用这个脚本之前,please enable Sheets API at Advanced Google services.

function copyRowtoSheet3() {
  var spreadsheetId = "1Aw11LiKzyezfrTQIuTsJPhUFtz8RPqLCc8FlIiy0ZlE";
  var ss = SpreadsheetApp.openById(spreadsheetId);
  var s1 = ss.getSheetByName('Sheet1');
  var s2 = ss.getSheetByName('Sheet2');

  // 1. Retrieve values from "Sheet1" and "Sheet2",
  var values1 = s1.getDataRange().getValues();
  var values2 = s2.getRange(1, 1, s2.getLastRow(), 1).getValues();

  // 2. Create an object using values2.
  var obj = values2.reduce((o, [e]) => {
    o[e] = null;
    return o;
  }, {});

  // 3. Create resultArray using values1 and obj.
  var resultArray = values1.filter(([,b]) => b in obj);

  // 4. Put resultArray to Sheet3.
  Sheets.Spreadsheets.Values.update({values: resultArray}, spreadsheetId, "Sheet3", {valueInputOption: "USER_ENTERED"});
}

注意:

  • 在这种情况下,请在脚本编辑器中启用 V8。

参考资料:

如果我误解了您的问题并且这不是您想要的结果,我深表歉意。

【讨论】:

  • 感谢您对此的详细解释!这正是我所需要的,所以你很感激。这确实有助于加快运行此代码的时间,并且以某种方式设法在 20 分钟内运行所有 135,000 行,而 395 个电话号码。太棒了!
  • @Garrett Kidd 感谢您的回复和测试。我很高兴你的问题得到了解决。也谢谢你。
  • Tanaike,我还有一个关于这个脚本的快速问题。在我让脚本比较“Sheet1”的“B”列和“Sheet2”的“A”列的值之前,如果它们相同,请将“Sheet1”的行放到“Sheet3”。我如何将其从选择 B 列更改为在工作表 1 中选择 N 列?我尝试更改为var resultArray = values1.filter(([,n]) =&gt; n in obj);,但没有成功。想法?
  • @Garrett Kidd 关于你的新问题,我想支持你。但我必须为我糟糕的英语水平道歉。不幸的是,我无法理解你的新问题。为了正确理解您的新问题,您可以通过包含详细信息将其作为新问题发布吗?通过这个,我想想想你的新问题。如果您能合作解决您的问题,我很高兴。
  • 请看一下我根据您的建议发布的新帖子。 stackoverflow.com/questions/60951952/…
猜你喜欢
  • 1970-01-01
  • 2022-01-26
  • 2015-10-25
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多