Что такое цикл и зачем он нужен?
Цикл в программировании – это конструкция, позволяющая многократно выполнять блок кода до тех пор, пока соблюдается определенное условие. В 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() (где это возможно): Эти методы часто более лаконичны и могут быть более производительными, чем классические циклы.
Тщательно тестируйте циклы: Убедитесь, что цикл работает правильно для всех возможных входных данных, включая граничные случаи (пустой массив, нулевое количество итераций).