Google Apps Script: Как организовать цикл по массиву?

Что такое массив в Google Apps Script?

В Google Apps Script, как и в JavaScript, массив – это упорядоченная коллекция элементов, каждый из которых имеет свой индекс. Индексы начинаются с 0. Массивы могут содержать элементы разных типов данных: числа, строки, булевы значения, объекты и даже другие массивы. Массивы динамичны, то есть их размер может изменяться во время выполнения скрипта.

Зачем нужны циклы для обработки массивов?

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

Обзор основных типов циклов, используемых с массивами

Для итерации по массивам в Google Apps Script наиболее часто используются следующие типы циклов:

for: Классический цикл с числовым индексом.

forEach: Метод массива, предоставляющий упрощенный способ итерации.

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

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

Цикл `for` для итерации по массиву

Синтаксис цикла `for`

Цикл for имеет следующий синтаксис:

for (initialization; condition; increment) {
  // Код, выполняемый на каждой итерации
}

initialization: Инициализация счетчика цикла.

condition: Условие, при котором цикл продолжает выполняться.

increment: Изменение счетчика цикла после каждой итерации.

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

/**
 * Суммирует элементы числового массива, используя цикл for.
 * @param {number[]} arr Числовой массив.
 * @return {number} Сумма элементов массива.
 */
function sumArrayForLoop(arr: number[]): number {
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
  }
  return sum;
}

const numbers: number[] = [1, 2, 3, 4, 5];
const total: number = sumArrayForLoop(numbers);
Logger.log(total); // Выводит: 15

Доступ к элементам массива внутри цикла `for`

Доступ к элементам массива осуществляется с помощью квадратных скобок и индекса элемента, например, arr[i]. Важно помнить, что индексация начинается с 0.

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

Для повышения производительности, особенно при работе с большими массивами, рекомендуется кешировать длину массива в отдельную переменную. Это позволяет избежать повторного вызова свойства .length на каждой итерации.

/**
 * Суммирует элементы числового массива с оптимизацией длины, используя цикл for.
 * @param {number[]} arr Числовой массив.
 * @return {number} Сумма элементов массива.
 */
function sumArrayForLoopOptimized(arr: number[]): number {
  let sum = 0;
  const len: number = arr.length; // Кешируем длину массива
  for (let i = 0; i < len; i++) {
    sum += arr[i];
  }
  return sum;
}

Цикл `forEach` для упрощенной итерации

Синтаксис метода `forEach`

Метод forEach является методом массива и принимает функцию обратного вызова (callback function) в качестве аргумента. Эта функция вызывается для каждого элемента массива.

array.forEach(function(element, index, array) {
  // Код, выполняемый для каждого элемента
});

element: Текущий элемент массива.

index: Индекс текущего элемента.

array: Сам массив.

Преимущества использования `forEach`

forEach предоставляет более лаконичный и читаемый синтаксис по сравнению с циклом for. Он также автоматически обрабатывает итерацию по всем элементам массива, что снижает вероятность ошибок, связанных с индексами.

Примеры использования `forEach` с анонимными функциями

/**
 * Выводит в лог каждый элемент массива, используя forEach.
 * @param {string[]} arr Массив строк.
 */
function logArrayElements(arr: string[]): void {
  arr.forEach(function(element) {
    Logger.log(element);
  });
}

const names: string[] = ["Alice", "Bob", "Charlie"];
logArrayElements(names); // Выводит: Alice, Bob, Charlie (в лог)

Можно также использовать стрелочные функции (arrow functions) для еще более краткого синтаксиса:

/**
 * Выводит в лог каждый элемент массива, используя forEach и стрелочную функцию.
 * @param {string[]} arr Массив строк.
 */
function logArrayElementsArrow(arr: string[]): void {
  arr.forEach(element => Logger.log(element));
}

Передача дополнительных параметров в `forEach`

Хотя forEach обычно используют с анонимными функциями, можно передать контекст (this) вторым аргументом. Это полезно, когда необходимо использовать методы объекта внутри функции обратного вызова.

Реклама

Цикл `for…in` и `for…of` (особенности применения к массивам)

Цикл `for…in`: итерация по индексам (ключам)

Цикл for...in предназначен для перебора свойств объекта. В контексте массивов он итерирует по индексам массива (ключам).

/**
 * Выводит в лог индексы массива, используя for...in.
 * @param {any[]} arr Массив.
 */
function logArrayIndices(arr: any[]): void {
  for (let index in arr) {
    Logger.log(index); // index - это строка!
  }
}

const data: any[] = [10, 20, 30];
logArrayIndices(data); // Выводит: 0, 1, 2 (как строки)

Особенности использования `for…in` с массивами (важно помнить про порядок и наследуемые свойства)

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

Цикл `for…of`: итерация по значениям (ES6)

Цикл for...of (представлен в ES6) предназначен для итерации по значениям элементов массива. Он более безопасен и удобен, чем for...in, и гарантирует порядок итерации.

/**
 * Выводит в лог значения массива, используя for...of.
 * @param {any[]} arr Массив.
 */
function logArrayValues(arr: any[]): void {
  for (let value of arr) {
    Logger.log(value);
  }
}

const values: any[] = ["A", "B", "C"];
logArrayValues(values); // Выводит: A, B, C

Сравнение `for…in` и `for…of` при работе с массивами

В большинстве случаев for...of является предпочтительным выбором для итерации по массивам, поскольку он итерирует по значениям, гарантирует порядок и не включает наследуемые свойства. for...in следует использовать только в тех случаях, когда необходимо перебрать индексы массива, и вы понимаете все его особенности и ограничения.

Практические примеры и распространенные ошибки

Пример: суммирование элементов массива

Уже представлен в разделе про for. Можно использовать и forEach:

/**
 * Суммирует элементы числового массива, используя forEach.
 * @param {number[]} arr Числовой массив.
 * @return {number} Сумма элементов массива.
 */
function sumArrayForEach(arr: number[]): number {
  let sum = 0;
  arr.forEach(element => sum += element);
  return sum;
}

Пример: фильтрация элементов массива

/**
 * Фильтрует элементы массива, оставляя только четные числа.
 * @param {number[]} arr Числовой массив.
 * @return {number[]} Новый массив, содержащий только четные числа.
 */
function filterEvenNumbers(arr: number[]): number[] {
  const evenNumbers: number[] = [];
  arr.forEach(element => {
    if (element % 2 === 0) {
      evenNumbers.push(element);
    }
  });
  return evenNumbers;
}

const numbersToFilter: number[] = [1, 2, 3, 4, 5, 6];
const even: number[] = filterEvenNumbers(numbersToFilter);
Logger.log(even); // Выводит: [2, 4, 6]

Пример: преобразование элементов массива

/**
 * Преобразует массив чисел в массив строк, добавляя префикс "Number: ".
 * @param {number[]} arr Числовой массив.
 * @return {string[]} Новый массив строк.
 */
function transformNumbersToStrings(arr: number[]): string[] {
  const stringArray: string[] = [];
  arr.forEach(element => stringArray.push("Number: " + element));
  return stringArray;
}

const numbersToTransform: number[] = [7, 8, 9];
const strings: string[] = transformNumbersToStrings(numbersToTransform);
Logger.log(strings); // Выводит: ["Number: 7", "Number: 8", "Number: 9"]

Распространенные ошибки при работе с циклами и массивами (индексы, границы)

Выход за границы массива: Попытка доступа к элементу с индексом, который меньше 0 или больше или равен длине массива, приведет к ошибке RangeError или undefined.

Неправильная инициализация цикла: Ошибка в начальном значении счетчика или в условии завершения цикла может привести к пропуску элементов или бесконечному циклу.

Использование for...in вместо for...of: Как уже упоминалось, for...in не предназначен для итерации по массивам, если важен порядок элементов или есть риск включения нежелательных свойств. Всегда используйте for...of для этих целей.

Неправильное изменение массива внутри цикла: Изменение размера массива (добавление или удаление элементов) внутри цикла может привести к непредсказуемым результатам. В таких случаях лучше использовать методы массива, такие как filter, map или reduce.


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