簡體   English   中英

優化二維數組的迭代

[英]Optimize iteration of 2-dimensional array

我正在嘗試優化 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())
}

如果我注釋掉以下代碼行“sheet.deleteRow(r + 1)”,腳本幾乎立即完成,因此這似乎是減慢腳本執行速度的罪魁禍首。 是否有更有效的解決方案來解決這個問題?

不是通過迭代刪除一行,而是在腳本末尾使用deleteRows(rowPosition, howMany)一次刪除所有行。 這行代碼可能類似於以下內容:

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

深入了解 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 行。

希望它無論如何都有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM