Работа с массивами данных — неотъемлемая часть разработки в Google Apps Script, особенно при взаимодействии с сервисами Google Workspace, такими как Google Sheets, Google Ads или Google Analytics. Часто возникает задача очистки данных от повторяющихся записей.
Важность удаления дубликатов в массивах данных
Дубликаты в массивах могут приводить к неверным расчетам, искажению статистики и неэффективной обработке данных. Например, при анализе списка ключевых слов из рекламных кампаний дубликаты могут завысить показатели частоты или привести к некорректной оценке эффективности. Удаление дубликатов — это базовый шаг предварительной обработки данных, обеспечивающий их точность и надежность.
Обзор различных подходов к удалению дубликатов
В Google Apps Script, основанном на JavaScript, существует несколько эффективных способов удаления дубликатов из массива. Мы рассмотрим три основных подхода:
- Использование методов
filter()иindexOf(). - Применение встроенного объекта
Set. - Использование вспомогательного объекта для отслеживания уникальных элементов.
Каждый метод имеет свои особенности, преимущества и недостатки, особенно в контексте производительности и читаемости кода.
Использование filter() и indexOf() для Удаления Дубликатов
Классический подход, основанный на стандартных методах массива JavaScript.
Подробное объяснение метода filter()
Метод filter() создает новый массив, содержащий только те элементы исходного массива, для которых переданная функция обратного вызова (callback) возвращает true. Он итерирует по каждому элементу массива, применяя к нему условие фильтрации.
Использование indexOf() для определения уникальности элементов
Метод indexOf() возвращает индекс первого вхождения указанного элемента в массиве. Если indexOf(element) равен текущему индексу элемента в процессе итерации filter(), это означает, что данный элемент встречается в массиве впервые. Именно на этом свойстве основан механизм удаления дубликатов: мы оставляем только те элементы, у которых индекс первого вхождения совпадает с их текущим индексом.
Пример кода: удаление дубликатов с использованием filter() и indexOf()
Предположим, у нас есть массив идентификаторов конверсий из Google Ads, и нам нужно получить только уникальные ID.
/**
* Удаляет дубликаты из массива строк с использованием filter и indexOf.
*
* @param {string[]} data Массив строк (например, ID конверсий).
* @return {string[]} Новый массив, содержащий только уникальные строки.
* @customfunction
*/
function removeDuplicatesFilterIndexOf(data) {
if (!Array.isArray(data)) {
Logger.log('Предоставленные данные не являются массивом.');
return [];
}
/**
* @param {string} value Текущий элемент массива.
* @param {number} index Текущий индекс элемента.
* @param {string[]} self Ссылка на исходный массив.
* @return {boolean} true, если элемент уникален (первое вхождение), иначе false.
*/
const filterCallback = (value, index, self) => {
return self.indexOf(value) === index;
};
const uniqueData = data.filter(filterCallback);
return uniqueData;
}
// Пример использования:
const conversionIds = ['AW-123', 'AW-456', 'AW-123', 'AW-789', 'AW-456'];
const uniqueConversionIds = removeDuplicatesFilterIndexOf(conversionIds);
Logger.log(uniqueConversionIds); // ['AW-123', 'AW-456', 'AW-789']
Анализ производительности этого метода
Основной недостаток этого подхода — его вычислительная сложность. Для каждого элемента массива метод indexOf() потенциально проходит по части массива снова. В худшем случае это приводит к сложности O(n²), где n — количество элементов в массиве. Для небольших массивов это приемлемо, но на больших объемах данных (тысячи и десятки тысяч элементов) производительность может значительно снижаться.
Применение Объекта Set для Удаления Дубликатов
Современный и часто наиболее эффективный способ удаления дубликатов в JavaScript (и, следовательно, в Google Apps Script) — использование объекта Set.
Введение в объект Set и его преимущества
Set — это коллекция, которая хранит только уникальные значения любого типа. Попытка добавить существующий элемент в Set игнорируется. Это свойство делает Set идеальным инструментом для дедупликации. Операции добавления, удаления и проверки наличия элемента в Set в среднем имеют сложность O(1).
Преобразование массива в Set и обратно
Процесс удаления дубликатов с помощью Set прост:
- Создать новый
Setиз исходного массива. Дубликаты будут автоматически удалены при созданииSet. - Преобразовать
Setобратно в массив. Это можно сделать с помощьюArray.from()или оператора расширения (...).
Пример кода: удаление дубликатов с использованием Set
Рассмотрим пример с массивом URL страниц сайта, полученных из Google Analytics API.
/**
* Удаляет дубликаты из массива с использованием объекта Set.
*
* @param {any[]} data Массив с элементами любого типа.
* @return {any[]} Новый массив с уникальными элементами.
* @customfunction
*/
function removeDuplicatesWithSet(data) {
if (!Array.isArray(data)) {
Logger.log('Предоставленные данные не являются массивом.');
return [];
}
// Создаем Set из массива - дубликаты удаляются автоматически
const uniqueSet = new Set(data);
// Преобразуем Set обратно в массив
const uniqueArray = Array.from(uniqueSet);
// Альтернатива: const uniqueArray = [...uniqueSet];
return uniqueArray;
}
// Пример использования:
const pageUrls = [
'/blog/article1',
'/products/itemA',
'/blog/article1', // Дубликат
'/contact',
'/products/itemA' // Дубликат
];
const uniquePageUrls = removeDuplicatesWithSet(pageUrls);
Logger.log(uniquePageUrls); // ['/blog/article1', '/products/itemA', '/contact']
Сравнение производительности Set с filter() и indexOf()
Метод с использованием Set значительно производительнее, особенно на больших массивах. Его временная сложность обычно составляет O(n), так как каждый элемент массива обрабатывается один раз при создании Set. Это делает Set предпочтительным выбором для большинства задач дедупликации в Google Apps Script.
Удаление Дубликатов с Использованием Объекта для Отслеживания
Еще один подход, который был популярен до широкого распространения Set, — использование обычного объекта JavaScript в качестве хеш-таблицы или словаря для отслеживания уже встреченных элементов.
Использование объекта в качестве хеш-таблицы для отслеживания уникальных элементов
Идея заключается в итерации по исходному массиву. Для каждого элемента проверяется, существует ли уже ключ с таким значением в объекте-трекере. Если ключа нет, элемент добавляется в результирующий массив, а соответствующий ключ (со значением true или любым другим маркером) добавляется в объект-трекер.
Пример кода: удаление дубликатов с использованием объекта
Представим, что нужно получить уникальные UTM-метки из списка URL.
/**
* Удаляет дубликаты из массива строк, используя объект для отслеживания.
*
* @param {string[]} data Массив строк (например, UTM-метки).
* @return {string[]} Новый массив с уникальными строками.
* @customfunction
*/
function removeDuplicatesWithObject(data) {
if (!Array.isArray(data)) {
Logger.log('Предоставленные данные не являются массивом.');
return [];
}
const seen = {}; // Объект для отслеживания встреченных элементов
const uniqueArray = [];
for (let i = 0; i < data.length; i++) {
const item = data[i];
// Проверяем, является ли строка ключом в объекте 'seen'
// Используем Object.prototype.hasOwnProperty.call для безопасности
if (!Object.prototype.hasOwnProperty.call(seen, item)) {
seen[item] = true; // Помечаем элемент как встреченный
uniqueArray.push(item);
}
}
return uniqueArray;
}
// Пример использования:
const utmSources = ['google', 'facebook', 'google', 'linkedin', 'facebook', 'google'];
const uniqueUtmSources = removeDuplicatesWithObject(utmSources);
Logger.log(uniqueUtmSources); // ['google', 'facebook', 'linkedin']
Преимущества и недостатки этого подхода
- Преимущества: Производительность сравнима с методом
Set(обычно O(n)), так как проверка наличия ключа в объекте в среднем выполняется за O(1). Может быть полезен в средах, гдеSetпо каким-то причинам недоступен (хотя в Google Apps ScriptSetподдерживается). - Недостатки:
- Работает корректно в основном для массивов примитивных типов (строки, числа), так как объекты и другие не примитивные типы будут преобразованы в строки при использовании в качестве ключей объекта (например,
{}['[object Object]'] = true). - Требует написания большего количества кода по сравнению с лаконичным
Set. - Может возникнуть конфликт, если элементы массива сами являются строками, совпадающими со встроенными свойствами объекта (например,
'constructor','toString'). ИспользованиеObject.prototype.hasOwnProperty.callсмягчает эту проблему.
- Работает корректно в основном для массивов примитивных типов (строки, числа), так как объекты и другие не примитивные типы будут преобразованы в строки при использовании в качестве ключей объекта (например,
Сравнение и Выбор Метода Удаления Дубликатов
Выбор оптимального метода зависит от конкретной ситуации, но есть общие рекомендации.
Факторы, влияющие на выбор метода (размер массива, типы данных)
- Размер массива: Для маленьких массивов (десятки, сотни элементов) разница в производительности между методами может быть незначительной. Для больших массивов (тысячи и более) методы
Setи объект-трекер значительно превосходятfilter/indexOf. - Типы данных:
Setуниверсален и корректно работает с различными типами данных (включая объекты, хотя идентичность объектов сравнивается по ссылке). Метод с объектом-трекером лучше всего подходит для примитивов (строк, чисел).filter/indexOfтакже работает с разными типами, но медленнее. - Читаемость и простота кода: Метод с
Setявляется наиболее лаконичным и выразительным. - Совместимость: Все три метода хорошо поддерживаются средой выполнения Google Apps Script.
Рекомендации по выбору оптимального метода
- Используйте
Setпо умолчанию: Это наиболее современный, производительный и лаконичный способ для большинства задач удаления дубликатов в Google Apps Script. - Рассмотрите
filter/indexOf: Если требуется сохранить порядок элементов и работать только с первым вхождением, или если код должен быть понятен разработчикам, менее знакомым сSet, этот метод может быть вариантом (при условии небольшого размера массива). - Используйте объект-трекер: В редких случаях, когда работа идет исключительно со строками или числами и требуется максимальный контроль над процессом или по каким-то причинам
Setиспользовать нежелательно.
Заключение и дальнейшие шаги
Удаление дубликатов — частая задача при обработке данных в Google Apps Script. Мы рассмотрели три основных метода: filter/indexOf, Set и объект-трекер. В большинстве случаев использование Set является наиболее предпочтительным благодаря его производительности и простоте. Выбор конкретного метода должен основываться на анализе размера данных, их типов и требований к производительности вашего скрипта. Понимание этих подходов позволит вам писать более эффективный и надежный код для автоматизации задач в Google Workspace.