Циклы в Google Apps Script: как организовать повторение действий?

Что такое цикл и зачем он нужен?

Цикл в программировании – это конструкция, позволяющая многократно выполнять блок кода до тех пор, пока соблюдается определенное условие. В Google Apps Script циклы необходимы для автоматизации повторяющихся задач, обработки больших объемов данных (например, строк в Google Sheets) и реализации сложных алгоритмов.

Основные типы циклов в Google Apps Script

В Google Apps Script доступны следующие типы циклов:

for: Цикл с заданным количеством итераций.

while: Цикл, выполняющийся до тех пор, пока условие истинно.

do...while: Цикл, аналогичный while, но гарантированно выполняющийся хотя бы один раз.

for...in: Цикл для перебора свойств объекта.

for...of: Цикл для перебора значений итерируемого объекта (массива, строки, и т.д.).

Когда какой цикл использовать: краткий обзор

for: Когда известно количество итераций (например, перебор элементов массива).

while: Когда условие продолжения цикла зависит от данных, полученных в процессе его выполнения (например, чтение данных из Google Sheets до пустой строки).

do...while: Когда необходимо гарантировать хотя бы одно выполнение тела цикла.

for...in: Когда нужно перебрать свойства объекта (например, параметры конфигурации).

for...of: Когда нужно перебрать значения массива или строки.

Цикл `for` в Google Apps Script

Синтаксис цикла `for` и его элементы

Синтаксис цикла for выглядит следующим образом:

for (начальное выражение; условие; выражение приращения) {
  // Код, который будет выполняться на каждой итерации
}

начальное выражение: Инициализирует счетчик цикла (обычно это переменная-индекс).

условие: Условие, при котором цикл будет продолжаться. Если условие ложно, цикл завершается.

выражение приращения: Изменяет значение счетчика цикла после каждой итерации (обычно это инкремент или декремент).

Примеры использования цикла `for`: итерация по массивам и диапазонам

Итерация по массиву:

/**
 * Функция для расчета общего бюджета рекламных кампаний.
 * @param {number[]} budgets - Массив бюджетов кампаний.
 * @return {number} - Суммарный бюджет.
 */
function calculateTotalBudget(budgets: number[]): number {
  let totalBudget: number = 0;
  for (let i: number = 0; i < budgets.length; i++) {
    totalBudget += budgets[i];
  }
  return totalBudget;
}

// Пример использования:
const campaignBudgets: number[] = [100, 200, 150, 300];
const total: number = calculateTotalBudget(campaignBudgets);
Logger.log("Total budget: " + total);

Итерация по диапазону в Google Sheets:

/**
 * Функция для чтения данных из диапазона Google Sheets.
 */
function readDataFromSheet() {
  const ss: GoogleAppsScript.Spreadsheet.Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet: GoogleAppsScript.Spreadsheet.Sheet = ss.getActiveSheet();
  const range: GoogleAppsScript.Spreadsheet.Range = sheet.getDataRange();
  const values: any[][] = range.getValues();

  for (let row: number = 0; row < values.length; row++) {
    for (let col: number = 0; col < values[row].length; col++) {
      Logger.log("Cell [" + row + ", " + col + "]: " + values[row][col]);
    }
  }
}

Расширенные возможности цикла `for`: вложенные циклы

Вложенные циклы позволяют выполнять итерацию по двумерным структурам данных, таким как матрицы или таблицы. Например:

/**
 * Функция для вывода таблицы умножения.
 */
function multiplicationTable() {
  for (let i: number = 1; i <= 10; i++) {
    let row: string = "";
    for (let j: number = 1; j <= 10; j++) {
      row += (i * j) + "\t";
    }
    Logger.log(row);
  }
}

Оптимизация циклов `for`: повышение производительности

Кэширование длины массива: Вместо вызова array.length на каждой итерации, сохраните значение в переменной.

Избегайте сложных вычислений внутри цикла: По возможности, вынесите вычисления за пределы цикла.

Используйте Array.forEach() (если возможно): Для простых операций с массивами forEach() может быть более производительным.

Цикл `while` и `do…while` в Google Apps Script

Синтаксис и отличия циклов `while` и `do…while`

while:

while (условие) {
  // Код, который будет выполняться, пока условие истинно
}
Реклама

do...while:

do {
  // Код, который будет выполнен хотя бы один раз
} while (условие);

Основное отличие – цикл do...while всегда выполняется хотя бы один раз, даже если условие изначально ложно.

Примеры использования циклов `while` и `do…while` (например, чтение данных до определенного условия)

Чтение данных из Google Sheets до пустой строки:

/**
 * Функция для чтения данных из столбца Google Sheets до пустой ячейки.
 */
function readDataUntilEmpty() {
  const ss: GoogleAppsScript.Spreadsheet.Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet: GoogleAppsScript.Spreadsheet.Sheet = ss.getActiveSheet();
  let row: number = 1;
  let value: any = sheet.getRange(row, 1).getValue();

  while (value !== "") {
    Logger.log("Value at row " + row + ": " + value);
    row++;
    value = sheet.getRange(row, 1).getValue();
  }
}

Пример с do...while (менее распространенный, но для демонстрации):

let i: number = 0;
do {
  Logger.log("This will run once even if i is initially greater than 5");
  i++;
} while (i < 5);

Разница между `while` и `do…while` и выбор подходящего цикла

Выбирайте while, если необходимо проверить условие перед выполнением кода. Выбирайте do...while, если необходимо гарантировать хотя бы одно выполнение кода, даже если условие сразу ложно.

Цикл `for…in` и `for…of` в Google Apps Script

Цикл `for…in`: итерация по свойствам объекта

Цикл for...in используется для перебора свойств объекта. Важно: порядок перебора свойств не гарантируется.

const campaign: object = {
  name: "Summer Sale",
  budget: 500,
  platform: "Google Ads"
};

for (const property in campaign) {
  Logger.log("Property: " + property + ", Value: " + campaign[property]);
}

Цикл `for…of`: итерация по значениям итерируемого объекта (массива, строки)

Цикл for...of используется для перебора значений итерируемого объекта. Под итерируемым объектом понимается массив, строка, Map, Set и т.д.

const keywords: string[] = ["shoes", "summer", "sale"];

for (const keyword of keywords) {
  Logger.log("Keyword: " + keyword);
}

Сравнение циклов `for…in` и `for…of` и рекомендации по использованию

for...in перебирает ключи объекта (имена свойств).

for...of перебирает значения итерируемого объекта.

Используйте for...in для перебора свойств объектов. Используйте for...of для перебора значений массивов, строк и других итерируемых объектов. Важно помнить, что for...in не рекомендуется использовать для перебора массивов, так как он может перебирать и другие свойства, добавленные к массиву (например, методы).

Управление циклами: `break` и `continue`

Оператор `break`: прерывание цикла

Оператор break немедленно завершает выполнение цикла.

Оператор `continue`: переход к следующей итерации

Оператор continue пропускает текущую итерацию цикла и переходит к следующей.

Примеры использования `break` и `continue` для управления логикой циклов

break (поиск ключевого слова в массиве):

const keywordsList: string[] = ["обувь", "лето", "распродажа", "акция"];
const targetKeyword: string = "распродажа";
let found: boolean = false;

for (const keyword of keywordsList) {
  if (keyword === targetKeyword) {
    Logger.log("Найдено ключевое слово: " + keyword);
    found = true;
    break; // Завершаем цикл, так как ключевое слово найдено
  }
}

if (!found) {
  Logger.log("Ключевое слово не найдено.");
}

continue (пропуск нечетных чисел):

for (let i: number = 1; i <= 10; i++) {
  if (i % 2 !== 0) {
    continue; // Пропускаем нечетные числа
  }
  Logger.log("Четное число: " + i);
}

Практические советы и лучшие практики при работе с циклами в Google Apps Script

Используйте понятные имена переменных: Имена переменных-счетчиков (i, j) должны быть понятны в контексте задачи. Если итерируете массив бюджетов, лучше использовать budgetIndex вместо i.

Избегайте бесконечных циклов: Убедитесь, что условие завершения цикла когда-нибудь станет ложным. Бесконечный цикл может привести к зависанию скрипта.

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

Используйте Array.forEach(), Array.map(), Array.filter() (где это возможно): Эти методы часто более лаконичны и могут быть более производительными, чем классические циклы.

Тщательно тестируйте циклы: Убедитесь, что цикл работает правильно для всех возможных входных данных, включая граничные случаи (пустой массив, нулевое количество итераций).


Добавить комментарий