优化二维数组的迭代

时间:2017-10-26 21:06:22

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

我正在尝试优化Google Apps脚本,该脚本以反向(从下到上)迭代电子表格中的行。脚本检查行中的第一个单元格(如果过去15天)并检查第12列中的字符串"是"如果两个条件都为真,则行从一个工作表移动到另一个工作表。

我遇到的麻烦是我超过规定的时间(6分钟),迭代2500行的所有数据,并期望增长得更大。

我确信这里已经多次回答了类似的问题,但鉴于我目前的编程技能水平,我无法应用我在这里找到的解决方案。非常感谢任何帮助。

这是工作表的格式:

 1st column                 12th column
+-----------+-----/ /-----+-------------+
|  Date     |             | Refunded?   |
+-----------+-----/ /-----+-------------+
| 8/29/2017 |             |     YES     |
+-----------+-----/ /-----+-------------+
| 9/26/2017 |             |      NO     |
+-----------+-----/ /-----+-------------+

这是剧本:

function myFunction() {
  // get compare date (15 days from current date 
  var compareDate = new Date().getTime() - (15 * (1000 * 60 * 60 * 24));

  // get sheets in spreadsheet
  var target = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
  var arr = [];

  // get 1st sheet data
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  var values = sheet.getDataRange().getValues();
  var r = values.length;

  // logic
  while (r >= 1) {
    if (values[r] && values[r][0].getTime() < compareDate && values[r][12].toLowerCase() == "yes" ) {        
      arr.push(values[r])
      sheet.deleteRow(r + 1)
    }
    r--;
  }

  target.getRange(target.getLastRow() + 1, 1, arr.length, arr[0].length).setValues(arr.reverse())
}

如果我注释掉以下代码行&#34; sheet.deleteRow(r + 1)&#34;该脚本几乎立即完成,所以这似乎是减慢脚本执行速度的罪魁祸首。这个问题会有更有效的解决方案吗?

2 个答案:

答案 0 :(得分:2)

不是通过迭代删除一行,而是使用deleteRows(rowPosition, howMany)在脚本末尾一次删除所有行。代码行可能类似于以下代码:

sheet.deleteRows(2, values.length - 1);

答案 1 :(得分:0)

深入了解Ruben关于一次删除多行的想法。在实际开始比较之前对数据进行排序是个好主意,这样所有最旧的“是”值都在底部。

要检查它,我设置了一张包含25000条记录的工作表:

function fillSheet() {
  var yesNo = ['yes', 'no'];
  var array = [];
  for (var i = 0; i < 25000; i++) {
    array[i] = [];
    var rand = yesNo[Math.floor(Math.random() * yesNo.length)];
    array[i].push(new Date(2016, 1, i), i, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, i + 8, i + 9, i + 10, rand);
  }
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  sheet.getRange(2, 1, array.length, array[0].length).setValues(array);
}

然后我修改了你的函数,以便它首先按照是/否和按日期对数据范围进行排序,然后进行检查(从这次的顶部开始)。

function myFunction() {
  // get compare date (15 days from current date 
  var compareDate = new Date().getTime() - (15 * (1000 * 60 * 60 * 24));

  // get sheets in spreadsheet
  var target = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
  var arr = [];

  // get 1st sheet data
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  var lastRow = sheet.getLastRow();
  var lastCol = sheet.getLastColumn();
  //sorting the range without the header row firstly by yes/no values and then by dates to make sure the oldest yes value are at the bottom and only then getting the values
  sheet.getRange(2, 1, lastRow - 1, lastCol).sort([{column: 13, ascending: true}, {column: 1, ascending: false}]);  
  var values = sheet.getRange(2, 1, lastRow - 1, lastCol).getValues();
  var r = 0;
  var firstMatch = 0;

  // logic
  while (r < values.length) {
    if (values[r] && values[r][0].getTime() < compareDate && values[r][12].toLowerCase() == "yes" ) {
      //looking for the first match which will be used in deleting the rows
      if (firstMatch === 0) {
        firstMatch = r + 1; 
      }
      else if (firstMatch > 0 && firstMatch > r) {
        firstMatch = r + 1;
      } 
      arr.push(values[r])
    }
    r++;
  }
  if (firstMatch > 0) {
    target.getRange(target.getLastRow() + 1, 1, arr.length, arr[0].length).setValues(arr); //this will insert the array twice in my case anв i'm not sure why
    sheet.deleteRows(firstMatch, values.length - firstMatch + 2); //+2 is empirical to make sure all rows are removed; not really sure where it comes from
    sheet.getRange(2, 1, lastRow, lastCol).sort({column: 1, ascending: true});
  }
}

这样,运行大约需要4秒钟。

但是有一些小问题:

  • 它尝试将生成的数组两次插入到目标工作表中,但显然不应该。也许与我现在使用的Vivaldi浏览器有关,不知道。

  • 经验的firstMatch,values.length - firstMatch + 2 - 再次不确定为什么它应该+2但是没有它它不会删除最后2行。

希望它无论如何都有帮助。