Google Apps Script: Как Сравнить Два Массива Данных?

Почему важно сравнивать массивы данных?

Сравнение массивов данных — фундаментальная операция в Google Apps Script, особенно при работе с данными из Google Sheets, Docs или внешних API. Эта задача возникает, когда необходимо:

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

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

Синхронизировать данные: Обеспечить, чтобы данные в разных таблицах Google Sheets были согласованы.

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

Обзор основных методов сравнения массивов

Существует несколько способов сравнения массивов в Google Apps Script, от простых и прямолинейных до более сложных и оптимизированных. Выбор метода зависит от размера массивов, типа данных, которые они содержат, и требуемой точности сравнения. Основные методы включают:

Циклы for: Простой, но часто не самый эффективный способ итерации по массивам и сравнения элементов.

Метод every(): Позволяет проверить, удовлетворяют ли все элементы массива заданному условию.

Метод filter(): Создает новый массив, содержащий только элементы, удовлетворяющие заданному условию, что полезно для обнаружения различий.

Метод reduce(): Позволяет свести массив к одному значению, например, для сравнения массивов объектов.

Простые методы сравнения массивов

Сравнение массивов с использованием цикла `for`

Самый базовый подход – использование цикла for для итерации по одному или обоим массивам и сравнения элементов по индексу. Этот метод прост в реализации, но может быть неэффективным для больших массивов.

/**
 * Сравнивает два массива, используя цикл for.
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @return {boolean} True, если массивы идентичны, иначе false.
 */
function compareArraysWithFor(arr1: any[], arr2: any[]): boolean {
  if (arr1.length !== arr2.length) {
    return false;
  }
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i] !== arr2[i]) {
      return false;
    }
  }
  return true;
}

// Пример использования
let array1 = [1, 2, 3];
let array2 = [1, 2, 3];
let array3 = [1, 2, 4];

console.log(compareArraysWithFor(array1, array2)); // true
console.log(compareArraysWithFor(array1, array3)); // false

Сравнение массивов с использованием метода `every()`

Метод every() позволяет проверить, удовлетворяют ли все элементы массива заданному условию. Этот метод можно использовать для сравнения массивов, если мы хотим убедиться, что каждый элемент одного массива соответствует элементу с тем же индексом в другом массиве.

/**
 * Сравнивает два массива, используя метод every().
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @return {boolean} True, если массивы идентичны, иначе false.
 */
function compareArraysWithEvery(arr1: any[], arr2: any[]): boolean {
  if (arr1.length !== arr2.length) {
    return false;
  }
  return arr1.every((element, index) => element === arr2[index]);
}

// Пример использования
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
let arr3 = [1, 2, 4];

console.log(compareArraysWithEvery(arr1, arr2)); // true
console.log(compareArraysWithEvery(arr1, arr3)); // false

Обнаружение различий: нахождение уникальных элементов в массивах

Чтобы найти элементы, которые присутствуют только в одном из массивов, можно использовать комбинацию методов filter() и includes().

/**
 * Находит уникальные элементы в первом массиве, которых нет во втором.
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @return {any[]} Массив уникальных элементов из первого массива.
 */
function findUniqueElements(arr1: any[], arr2: any[]): any[] {
  return arr1.filter(element => !arr2.includes(element));
}

// Пример использования
let array_1 = [1, 2, 3, 4, 5];
let array_2 = [3, 4, 5, 6, 7];

console.log(findUniqueElements(array_1, array_2)); // [1, 2]
console.log(findUniqueElements(array_2, array_1)); // [6, 7]

Продвинутые методы сравнения массивов

Сравнение массивов объектов: сравнение по свойствам

Если массивы содержат объекты, простое сравнение === не будет работать, так как оно сравнивает ссылки на объекты, а не их содержимое. В этом случае необходимо сравнивать объекты по их свойствам.

/**
 * Сравнивает два массива объектов по заданному свойству.
 * @param {object[]} arr1 Первый массив объектов.
 * @param {object[]} arr2 Второй массив объектов.
 * @param {string} property Свойство, по которому сравниваются объекты.
 * @return {boolean} True, если массивы объектов идентичны по заданному свойству, иначе false.
 */
function compareArraysOfObjects(arr1: object[], arr2: object[], property: string): boolean {
  if (arr1.length !== arr2.length) {
    return false;
  }
  for (let i = 0; i < arr1.length; i++) {
    if (arr1[i][property] !== arr2[i][property]) {
      return false;
    }
  }
  return true;
}

// Пример использования
let objects1 = [{id: 1, name: 'A'}, {id: 2, name: 'B'}];
let objects2 = [{id: 1, name: 'A'}, {id: 2, name: 'B'}];
let objects3 = [{id: 1, name: 'A'}, {id: 2, name: 'C'}];

console.log(compareArraysOfObjects(objects1, objects2, 'id')); // true
console.log(compareArraysOfObjects(objects1, objects3, 'name')); // false

Использование `reduce()` для сравнения массивов

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

Реклама
/**
 * Сравнивает два массива объектов, используя reduce().
 * @param {object[]} arr1 Первый массив объектов.
 * @param {object[]} arr2 Второй массив объектов.
 * @param {string[]} properties Массив свойств, по которым сравниваются объекты.
 * @return {boolean} True, если массивы объектов идентичны по заданным свойствам, иначе false.
 */
function compareArraysOfObjectsWithReduce(arr1: object[], arr2: object[], properties: string[]): boolean {
    if (arr1.length !== arr2.length) {
        return false;
    }

    return arr1.reduce((areEqual, obj1, index) => {
        if (!areEqual) return false; // Если предыдущие элементы не равны, дальше нет смысла сравнивать

        const obj2 = arr2[index];

        for (const property of properties) {
            if (obj1[property] !== obj2[property]) {
                return false; // Если хотя бы одно свойство не совпадает, элементы не равны
            }
        }

        return true; // Все свойства совпали, элементы равны
    }, true); // Начальное значение areEqual - true, предполагаем, что массивы равны, пока не найдем различие
}


// Пример использования
let objects_1 = [{id: 1, name: 'A', value: 10}, {id: 2, name: 'B', value: 20}];
let objects_2 = [{id: 1, name: 'A', value: 10}, {id: 2, name: 'B', value: 20}];
let objects_3 = [{id: 1, name: 'A', value: 10}, {id: 2, name: 'B', value: 21}];

console.log(compareArraysOfObjectsWithReduce(objects_1, objects_2, ['id', 'name', 'value'])); // true
console.log(compareArraysOfObjectsWithReduce(objects_1, objects_3, ['id', 'name', 'value'])); // false

Сравнение массивов разной длины

Обработка ситуаций с массивами разной длины

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

Сравнение подмножества массивов

Если необходимо сравнить подмножество массивов, можно использовать методы slice() для создания новых массивов с нужной длиной, а затем сравнивать их.

/**
 * Сравнивает подмножества двух массивов.
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @param {number} length Длина подмножества для сравнения.
 * @return {boolean} True, если подмножества массивов идентичны, иначе false.
 */
function compareArraySubsets(arr1: any[], arr2: any[], length: number): boolean {
  if (length > arr1.length || length > arr2.length) {
    throw new Error('Длина подмножества превышает длину одного из массивов.');
  }
  let subset1 = arr1.slice(0, length);
  let subset2 = arr2.slice(0, length);
  return compareArraysWithEvery(subset1, subset2);
}

// Пример использования
let arr_1 = [1, 2, 3, 4, 5];
let arr_2 = [1, 2, 3, 6, 7];

console.log(compareArraySubsets(arr_1, arr_2, 3)); // true
console.log(compareArraySubsets(arr_1, arr_2, 4)); // false

Оптимизация сравнения массивов и лучшие практики

Повышение производительности сравнения больших массивов

Для больших массивов, производительность сравнения становится критичной. Использование циклов for может быть неэффективным. В таких случаях следует рассмотреть возможность использования более продвинутых методов, таких как Set или сортировка массивов перед сравнением. Использование Set позволяет быстро проверять наличие элемента в массиве, что может значительно ускорить процесс сравнения.

/**
 * Сравнивает два массива, используя Set для повышения производительности.
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @return {boolean} True, если массивы содержат одни и те же элементы (не обязательно в том же порядке), иначе false.
 */
function compareArraysWithSet(arr1: any[], arr2: any[]): boolean {
    if (arr1.length !== arr2.length) {
        return false;
    }

    const set1 = new Set(arr1);
    const set2 = new Set(arr2);

    if (set1.size !== arr1.length || set2.size !== arr2.length) {
        return false; // Массивы содержат дубликаты
    }

    for (const element of set1) {
        if (!set2.has(element)) {
            return false;
        }
    }

    return true;
}

// Пример использования
let arr_1_set = [1, 2, 3, 4, 5];
let arr_2_set = [5, 4, 3, 2, 1];
let arr_3_set = [1, 2, 3, 4, 6];

console.log(compareArraysWithSet(arr_1_set, arr_2_set)); // true
console.log(compareArraysWithSet(arr_1_set, arr_3_set)); // false

Рекомендации по написанию читаемого и эффективного кода

Используйте понятные имена переменных и функций.

Добавляйте комментарии для объяснения сложных участков кода.

Разбивайте сложные задачи на более мелкие и простые функции.

Избегайте глобальных переменных.

Следуйте стандартам кодирования Google Apps Script.

Обработка ошибок и исключений при сравнении массивов

При сравнении массивов важно предусмотреть возможные ошибки и исключения. Например, массивы могут быть null или undefined, или содержать элементы несовместимых типов. Для обработки таких ситуаций используйте блоки try...catch и проверяйте типы данных перед выполнением операций сравнения.

/**
 * Безопасное сравнение двух массивов с обработкой ошибок.
 * @param {any[]} arr1 Первый массив.
 * @param {any[]} arr2 Второй массив.
 * @return {boolean | null} True, если массивы идентичны, false, если нет, null в случае ошибки.
 */
function safeCompareArrays(arr1: any[], arr2: any[]): boolean | null {
  try {
    if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
      throw new Error('Один или оба аргумента не являются массивами.');
    }
    return compareArraysWithEvery(arr1, arr2);
  } catch (e) {
    console.error('Ошибка при сравнении массивов:', e);
    return null;
  }
}

// Пример использования
let arr1_safe = [1, 2, 3];
let arr2_safe = [1, 2, 3];
let notAnArray = 'hello';

console.log(safeCompareArrays(arr1_safe, arr2_safe)); // true
console.log(safeCompareArrays(arr1_safe, notAnArray)); // null (и выведет сообщение об ошибке в консоль)

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