Как мне сделать меньше вызовов sheet.getRange и сократить время выполнения в двойном цикле

#javascript #google-apps-script #google-sheets

#javascript #google-apps-script #google-sheets

Вопрос:

Я хочу уменьшить вызовы sheet.getRange в следующей функции, потому что время выполнения истекло.

Я попытался переупорядочить циклы и проанализировать данные в виде двойного массива, однако размер моей электронной таблицы меняется каждый день, и мне нужно иметь возможность ссылаться на столбцы только по имени.

 function runDuplicateRemover() {
 var sheet= SpreadsheetApp.getActive().getSheetByName('Sheet 1');
 var rangeData = sheet.getDataRange();
 var lastRow = rangeData.getLastRow();
 var Cdata = sheet.getDataRange().getValues();
  // here I am accessing the column which is used to find duplicates
 var colCRM = Cdata[0].indexOf("CRM ID") 1;
 var arrayOfDuplicates = [];

  for(i=1; i<lastRow; i  ){
    var cellToCompare =  sheet.getRange(i 1,colCRM);
// I am just changing all the colors to see the execution
    cellToCompare.setBackground("#88b4fc");
    var crmToCompare =cellToCompare.getValue();
   //checks to see that this value is not already contained in the rows to delete
   if (!cellToCompare.isBlank() amp;amp; (arrayOfDuplicates.indexOf(i) 1)==0 ){
       arrayOfDuplicates.push(i);
       cellToCompare.setBackground("#f9d9f9");

   for (j = i 1; j<lastRow; j  ) {
      var cellCurrent = sheet.getRange(j 1,colCRM);
      cellCurrent.setBackground("#f2fc88");
      var crmCurrent = cellCurrent.getValue();   
      if (crmToCompare == crmCurrent) {

           arrayOfDuplicates.push(j);
           cellCurrent.setBackground("#fc92f1");

          }  
        }

       //pops last value since that's the only one I want to keep
      sheet.getRange(arrayOfDuplicates.pop() 1,colCRM).setBackground("#dbf7d4");

      }  
    }



   for (t = arrayOfDuplicates.length-1; t>=0; t--) {
      sheet.deleteRow(arrayOfDuplicates[t] 1);
    }
  }
  

Я хотел бы уменьшить количество вызовов sheet.getRange, однако я не знаю, как удалить строки, а затем вернуть данные обратно на лист, не нарушая порядок столбцов.

Комментарии:

1. Вы могли бы использовать Set. В каждой ячейке вы проверяете, существует ли элемент в наборе. Если элемент существует в наборе, то вы знаете, что это дубликат (и делайте с ними то, что хотите). Если элемента нет в наборе, то вы добавляете его, поскольку набор содержит только уникальные элементы, без дубликатов.

2. @acarlstein как бы с помощью set уменьшить мои вызовы getRange? Я уже проверяю, существует ли элемент с массивом.

3. Набор, как правило, использует хэш-таблицу в качестве базовой структуры данных, поэтому проверка элемента может быть O(1), а поиск элемента также может быть O(1).

4. Позвольте мне немного расширить свой комментарий. Вы используете массив дубликатов, а затем выполняете поиск с помощью indexOf() . Это означает, что ваша временная сложность O(n) . Почему? Поскольку в худшем случае вы должны перебирать весь массив, пока не найдете значение. Если вместо этого использовать Set , время может быть сокращено до O(1) по временной сложности, потому что Set использует HashTable . Способ доступа к элементам намного эффективнее; следовательно, вы можете выполнить то же самое, но быстрее.

5. Неважно. В Javascript ‘Set’ не реализован с использованием хэш-таблицы, как в других языках (и языках сценариев). Метод has() является O(n) . Вам придется реализовать это самостоятельно или найти кого-то в GitHub, кто его создал.