Как улучшить цикл for без получения времени ожидания во время выполнения,

#google-apps-script #google-sheets

#google-apps-script #google-sheets

Вопрос:

В настоящее время я работаю над проектом, который перекрестно проверяет 2 листа примерно с 500 циклами.

СПИСОК

Имя Фамилия DoB
Джудит Барраган 4/10/1959
Келли Бенитес 9/14/1993
Марта Bustos 1/12/1960
Робин Кэрролл 5/9/1954
Джанет Камеры 8/27/1949
Никки Corso 10/25/1957
Angella Decohen 5/23/1988
Дамиан Делани 6/26/1961
Анора Денисон 4/14/1998
Кристина Dimatulac 7/28/1959
Милосердие Erazo 3/14/1959
Мишель Фанара 11/20/1981
Шеннон Feldmann 9/10/1986
Alejandra Фрутос-Сильва 2/14/1978
Ребекка Успехи 7/14/2007
Jarely Агилера 6/8/2006
Jasmine Агийон 1/29/2007
Адриана Аланиз 10/4/2007
Бланка Ангел 11/3/2007
Фрэнси Ареллано 9/11/2007
Молли Barajas 10/1/2007
Эмили Барранко 9/12/2007
Valeria Bata 3/29/2007
Сарахи Cabeza 8/8/2007
Карла Cadena 3/31/2006
Эмили Cano 1/25/2007
Джанет Canul 4/27/2007
Кейтлин Кастанеда 3/26/2007
Жаклин Кастильо 1/22/2007
Мелани Колиндрес 6/8/2007
Ня Дэвис 8/8/2007
Кэри Delgadillo 2/10/2007
Gabriela Диас 6/25/2007
Хелен Диас 8/17/2007
Хейли Дюран 5/20/2007
Хейзел Флорес 9/7/2007
Кихерра Гамбоа 10/4/2007
Белен Гонсалес 4/23/2007
Саманта Гонсалес 10/16/2007
Ashlee Palacios 8/31/2006
Наоми Papaqui 5/17/2007
Karely Пакстор 10/21/2006
Мишель Пакстор 10/20/2007
Audra Перес 2/24/2007
Josueline Перес 10/30/2006
Яреци Пинеда 2/17/2007
Zuleyka Portela 9/10/2007
Jacqueline Prudencio 3/1/2007
Destiny Quiroz 5/10/2007
Kelcey Raiz 5/11/2007
Brianna Ramos 8/15/2007
Neydy Renderos 8/26/2007
Daiman Johnson 3/3/1968
Kimberley Rivas 11/2/2007
Michelle Dominguez 5/15/2005
Marleny Rodriguez 7/29/2007
Maria Roman 5/9/2006
Cristal Solis 9/29/2006
Carmela Torralba 6/28/2007
Dora Vasquez 5/14/2007
Cindy Vega 11/20/2007
Jennifer Velasco 6/30/2006
Chloe Wilson 10/8/2007
Melody Zacarias 5/17/2007
Hazel Zamora 1/27/2007
Kayden Alexander 2/6/2006
Yvette Alvarado 3/30/2006
Damian Delaney 6/26/1961
Kimberly Amezcua 7/14/2006
Kimberly Antonio 5/30/2006
Alicia Aquino 6/15/2006
Samantha Aquino 6/27/2006
Destiny Arauz 6/13/2006
Julissa Arroyo 5/26/2006
Cassandra Ayala 8/18/2006
Samantha Ayala 7/2/2006
Eva Azul 2/6/2006
Stacey Bacelis 4/4/2006
America Baires 7/17/2006
Ashley Barajas 6/10/2005
Janet Barrera 10/14/2005
Alisa Benitez 5/26/2006
Sara Bolanos-Mejia 1/12/2006
Ashley Mendez 6/22/2006
Ana Carvente 7/12/2006
Mia Castellanos 6/19/2006
Rosalma Cebreros 3/3/2006
Yosselin Celis 5/25/2005
Jacqueline Lucero 9/2/1974
Evelyn Chamu 1/30/2006
Nataly Chavez 2/27/2006
Juliana Coeto 10/4/2005
Shesith Covarrubias 12/8/2005
Ashley Cruz 7/20/2006
Erin Dakers 8/2/2007
Claudia Lopez 6/16/2007
Cristina Diaz 10/13/2005
Zoe Dighero 4/11/2006
Kaylynn Domingo 10/4/2006
Celeste Dominguez 6/1/2006
Lizzy Escobar 12/14/2005
Lilian Escorza 12/23/2005

REGISTRATION

First Name Last Name DoB
Jacqueline Lucero 9/2/1974
Ashley Mendez 6/22/2006
Hyobe Namkoong 6/19/2007
Hetzabel Sanchez 4/13/2005
cristal solis 9/29/2006
Briseida Lopez 5/22/2005
Daiman Johnson 3/3/1968
Kayleen Vasquez 12/9/2003
Ashley Aguilar 12/9/2003
Damian Delaney 6/26/1961
Michelle Dominguez 5/15/2005
Martha Bustos 1/12/1960
Jaqueline Granadino 9/6/2004
jacqueline granadino 9/6/2004
Жаклин гранадино 9/6/2004
Мария Gutierrez 11/30/2006
Клаудия Лопес 6/16/2007
Келли Бенитес 9/14/1993
Келли Бенитес 9/14/1993

Результат

Имя Фамилия DoB Запуск кода
Жаклин Lucero 9/2/1974 1980001
Эшли Мендес 6/22/2006 1980002
Cristal Солис 9/29/2006 1980003
Daiman Джонсон 3/3/1968 1980004
Дамиан Делани 6/26/1961 1980005
Мишель Домингес 5/15/2005 1980006
Марта Bustos 1/12/1960 1980007
Клаудия Лопес 6/16/2007 1980008
Келли Бенитес 9/14/1993 1980009

Пример таблицы данных моя проблема в том, что мой скрипт иногда получает время ожидания во время выполнения. Я вижу функцию map, но я не уверен, применима ли она для моей текущей проблемы.

вот мои листы, которые включены в мой скрипт. листы — это реестр, ответы формы 1, ссылка, результат. реестр и вкладка регистрация имеют общие столбцы (имя, фамилия, дата рождения)

 var SS              = SpreadsheetApp.getActiveSpreadsheet()
var rosterTab       = SS.getSheetByName('Roster')
var registrationTab = SS.getSheetByName('Responses 1')
var referenceTab    = SS.getSheetByName('Reference')
var resultTab       = SS.getSheetByName('Result') //this is where I posts all registered names that is on the roster tab.
var xLastRow        = registrationTab.getLastRow();
var yLastRow        = rosterTab.getLastRow();
var Data            = [];
var codeStart       = referenceTab.getRange('A1').getValue();
var rosterdata      = rosterTab.getRange(1,1,300,3).getValues();
var registerdata    = registrationTab.getRange(1,1,xLastRow,3).getValues();

for(var i = 0; i<yLastRow; i  (){
    for(var j = 0; j<xLastRow; j  (){
        if (rosterdata[i][0] === registerdata[j][0] amp;amp; rosterdata[i][1] === registerdata[j][1] amp;amp; rosterdata[i][2] === registerdata[j][2]){
            var rosterFname = registerdata[j][0];
            var rosterLname = registerdata[j][1];
            var rosterDoB   = registerdata[j][2];
            var rosterCode  = codeStart;

            Data.push([rosterFname,rosterLname,rosterDoB,rosterCode]);

            break;
        }
    }
}
resultTab.getRange( resultTab.getLastRow() 1, 1, Data.length,Data[0].length ).setValues(Data);
 

Есть ли другой способ приблизиться к этому сопоставлению без тайм-аута?

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

1. Я думаю, что ваш сценарий неполон, когда я увидел for(var i = 0; i<yLastRow; i (){ и for(var j = 0; j<xLastRow; j (){ . Итак, я обеспокоен тем, что ваш фактический сценарий может отличаться от вашего сценария показа. А также, в вашем вопросе, используются 3 листа, такие как «РЕЕСТР», «РЕГИСТРАЦИЯ» и «РЕЗУЛЬТАТ». В вашем скрипте используются 4 листа «Список», «Ответы 1», «Ссылка» и «Результат». И, когда я увидел ваш образец электронной таблицы, я не могу найти таблицу «Ответы 1» и «РЕГИСТРАЦИЯ». Поэтому я не могу понять ваш вопрос. Я прошу прощения за это. Могу я спросить вас о деталях вашего вопроса?

2. Привет @Tanaike Спасибо, что нашли время ответить на мой вопрос. Цель этого скрипта — проверять входящих владельцев регистрации из «Ответов на регистрационные формы» с помощью «Реестра». список уже заполнен из школы. Если владелец регистрации найден в реестре, он будет опубликован в результате с кодом #, найденным в листе «Ссылка».

3. Спасибо за ответ. Я все еще не могу понять ваш вопрос. Я не могу понять взаимосвязь между вашими образцами данных в вашем вопросе и вашей образцовой электронной таблицей. Могу я спросить вас об этом?

4. @Tanaike Я на самом деле ищу решение, если есть гораздо более эффективный способ или более быстрая функция для этого. моя текущая структура скрипта дает время ожидания во время выполнения, потому что он выполняет 500-600 циклов на имя в ответе.

5. Спасибо за ответ. Я снова должен извиниться за мой плохой английский. К сожалению, я все еще не могу понять ваш вопрос. Но я хотел бы попытаться понять это. Когда я смог правильно это понять, я хотел бы подумать о решении. Я был бы признателен, если бы вы могли простить мое плохое знание английского языка.

Ответ №1:

 function myfunky11() {
  const ss = SpreadsheetApp.getActive();
  const rosterTab = ss.getSheetByName('Roster');
  const registrationTab = ss.getSheetByName('Responses 1');
  const referenceTab = ss.getSheetByName('Reference');
  let rsh = ss.getSheetByName('Result'); 
  var data = [];
  const codeStart = referenceTab.getRange('A1').getValue();
  const ros = rosterTab.getRange(2, 1, rosterTab.getLastRow() - 1, 3).getDisplayValues().map(r => r[0]   r[1]   r[2]);
  const reg = registrationTab.getRange(2, 1, registrationTab.getLastRow() - 1, 3).getValues();
  reg.forEach(r => {
    let s = r[0].toString()   r[1].toString()   Utilities.formatDate(new Date(r[2]), Session.getScriptTimeZone(), "M/d/yyyy");
    if (ros.indexOf(s)>-1) {
      r.push(codeStart);
      data.push(r)
    }
  });
  rsh.clear();
  rsh.getRange(1, 1, data.length, data[0].length).setValues(data);
}
 

Теперь это работает

Ответ №2:

Вы можете обрабатывать все данные «Реестра» пакетами, отслеживая последнюю строку, которую вы обработали с помощью PropertiesService

 const LAST_PROCESSED_ROW_PROPERTY_KEY = 'lastProcessedRow';
const PROCESS_ROW_PER_BATCH           = 100;

var scriptProperties = PropertiesService.getScriptProperties();
var lastProcessedRow = scriptProperties.getProperty( LAST_PROCESSED_ROW_PROPERTY_KEY );

if ( lastProcessedRow === null ) {
    lastProcessedRow = 0;
}

// Your variables here

var yLastRow          = rosterTab.getLastRow();
var rowsToBeProcessed = PROCESS_ROW_PER_BATCH;

if ( lastProcessedRow == yLastRow ) {
    Logger.log( 'No new data to be processed' );

    return;
}

if ( yLastRow - lastProcessedRow < PROCESS_ROW_PER_BATCH ) {
    rowsToBeProcessed = yLastRow - lastProcessedRow;
}

var rosterdata = rosterTab.getRange( lastProcessedRow   1, 1, rowsToBeProcessed, 3 ).getValues();

for( var i = 0; i < rosterdata.length; i   ) {
    // Your data processing logic here
}

// Set data logic here

scriptProperties.setProperty( LAST_PROCESSED_ROW_PROPERTY_KEY, lastProcessedRow   rowsToBeProcessed );
 

Ответ №3:

Я считаю, что ваша цель заключается в следующем.

  • В вашей электронной таблице 3 листа.
  • Вы хотите получить значения из таблиц «Форма ответа 1» и «Реестр». Когда значения из столбцов «B» в «D» на листе «Форма ответа 1» совпадают со значениями столбцов «A» в «C» на листе «Реестр», вы хотите поместить их в лист «Результат» в качестве добавляемых значений.
  • Вы хотите снизить стоимость этого процесса.

В этом случае, как насчет следующего модифицированного сценария?

Модифицированный скрипт:

 function myFunction() {
  var SS = SpreadsheetApp.getActiveSpreadsheet();
  var rosterTab = SS.getSheetByName('Roster');
  var registrationTab = SS.getSheetByName('Form Response 1');
  var referenceTab = SS.getSheetByName('Reference');
  var resultTab = SS.getSheetByName('Result');
  var xLastRow = registrationTab.getLastRow();
  var yLastRow = rosterTab.getLastRow();
  var Data = [];
  var codeStart = referenceTab.getRange('A1').getValue();
  var rosterdata = rosterTab.getRange(1, 1, yLastRow, 3).getValues();
  var registerdata = registrationTab.getRange(2, 2, xLastRow - 1, 3).getValues();

  // I modified below script.
  // Create an object.
  var obj = rosterdata.reduce((o, [a,b,c]) => (o[a   b   c] = true, o), {});

  // Create an array for putting to sheet.
  var values = registerdata.reduce((ar, [a, b, c]) => {
    if (obj[a   b   c]) ar.push([a, b, c, codeStart]);
    return ar;
  }, []);
  
  // Put the array to the result sheet.
  if (values.length == 0) return;
  resultTab.getRange(resultTab.getLastRow()   1, 1, values.length, values[0].length).setValues(values);
}
 
  • В этой модификации создайте объект для поиска значений и создайте массив для добавления на лист, а созданный массив будет добавлен к таблице результатов. С помощью этого потока я подумал, что стоимость процесса может быть немного снижена.

Ссылка: