【问题标题】:Apps Script - For loop is slow. How to make it faster?Apps 脚本 - For 循环很慢。如何让它更快?
【发布时间】:2021-09-25 03:18:34
【问题描述】:

我的电子表格有一列 (A),其中包含 10.99 欧元、25.99 欧元等超过 1000 行的值。出于优化目的,我循环浏览此列并删除“EUR”标记并替换“。”和 ”,”。虽然代码有效,但我的问题是执行需要很长时间,而且对于数千种产品,有时会超时。我知道我可能没有遵循最佳实践,但由于我的 JavaScript 技能有限,这是我能想到的最佳解决方案。有什么帮助吗?

function myFunction() {
  var ss = SpreadsheetApp.getActive();
  var sheet = ss.getSheetByName('Table');
  var lastRow = sheet.getRange(1,1).getDataRegion(SpreadsheetApp.Dimension.ROWS).getLastRow();
  for (var i = 1; i < lastRow +1; i++) {
    var price = sheet.getRange(i,1).getValue();
    var removeCur = price.toString().replace(" EUR","").replace(".",",");
    sheet.getRange(i,1).setValue(removeCur);
  }
}

【问题讨论】:

  • 在每个for 循环迭代中都有一个 API 调用,这确实很慢。您需要做的是获取您的范围值,对每个值运行map(),然后将新数组一次粘贴到您的电子表格中。如果您愿意,可以在 Google Developers here 上了解更多关于最佳实践的信息。
  • 我没有看到接受的答案。为什么?您在等待另一个正确答案吗?
  • 尤里,谢谢你的精彩回答。标记为正确。

标签: javascript for-loop google-apps-script google-sheets


【解决方案1】:

这是一个经典的问题。经典答案——您需要将cell.getValue() 替换为range.getValues()。以这种方式获得二维数组。使用循环(或映射等)处理数组。然后使用range.setValues() 一次将数组的所有值设置回工作表上

https://developers.google.com/apps-script/guides/support/best-practices?hl=en

对于这种情况,它可能是这样的:

function main() {
  var ss    = SpreadsheetApp.getActive();
  var sheet = ss.getSheetByName('Table');
  var range = sheet.getDataRange();
  var data  = range.getValues(); // get a 2d array

  // process the array (make changes in first column)
  const changes = x => x.toString().replace(" EUR","").replace(".",",");
  data = data.map(x => [changes(x[0])].concat(x.slice(1,)));

  range.setValues(data);  // set the 2d array back to the sheet
}

以防万一这里是与循环相同的代码for

function main() {
  var ss    = SpreadsheetApp.getActive();
  var sheet = ss.getSheetByName('Table');
  var range = sheet.getDataRange();
  var data  = range.getValues();

  for (var i=0; i<data.length; i++) {
    data[i][0] = data[i][0].toString().replace(" EUR","").replace(".",",")
  }
  
  range.setValues(data);  
}

在这种情况下,for 循环可能看起来比 map 更干净。

如果您确定所有更改都将在 A 列中,如果您以这种方式更改函数中的第三行,则可以使脚本更快:

var range = sheet.getRange("A1:A" + sheet.getLastRow());

它将范围缩小到一列。

【讨论】:

    【解决方案2】:

    嗯,你可以做一些事情来改进你的代码,但不能保证它会帮助你更快,但我们会看到。

    这是更新版本

    function myFunction() {
       var ss = SpreadsheetApp.getActive();
       var sheet = ss.getSheetByName('Table');
       var lastRow = sheet.getRange(1,1).getDataRegion(SpreadsheetApp.Dimension.ROWS).getLastRow() + 1;
       var price;
       var removeCur;
       for (var i = 1; i < lastRow; i++) {
           price = sheet.getRange(i,1).getValue();
           removeCur = price.toString().replace(" EUR","").replace(".",",");
           sheet.getRange(i,1).setValue(removeCur);
       }
    }
    

    我做了什么:

    1. 第 5 行:我删除了循环中的 +1 并直接添加到 lastRow。如果您有 1000 行,您将保存 1000 个作业
    2. 第 6-7 行:删除了循环中的声明。如果您有 1000 行,您将节省 2000 次重新声明(不确定是否如此,但无论如何这是最佳做法)

    你可以使用正则表达式进行替换,所以你只做一次,但我认为它比较慢,所以我保留了 2 个替换

    【讨论】:

    • 感谢您的回答和改进。不幸的是,它仍然像以前一样慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 2023-02-16
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    相关资源
    最近更新 更多